Add a helper that will retrun true if a virStorageSource has backing
store. This will also aid in refactoring of the code further down.
---
src/conf/domain_conf.c | 2 +-
src/conf/storage_conf.c | 5 +++--
src/libvirt_private.syms | 2 ++
src/qemu/qemu_block.c | 4 ++--
src/qemu/qemu_cgroup.c | 4 ++--
src/qemu/qemu_domain.c | 6 ++---
src/qemu/qemu_driver.c | 9 ++++----
src/security/security_dac.c | 2 +-
src/security/security_selinux.c | 4 ++--
src/security/virt-aa-helper.c | 2 +-
src/storage/storage_backend_logical.c | 2 +-
src/storage/storage_source.c | 2 +-
src/storage/storage_util.c | 14 ++++++------
src/util/virstoragefile.c | 42 +++++++++++++++++++++++++++++------
src/util/virstoragefile.h | 6 +++++
tests/virstoragetest.c | 2 +-
16 files changed, 73 insertions(+), 35 deletions(-)
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 45fa57a14..3eb6c7f6f 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -26607,7 +26607,7 @@ virDomainDiskDefForeachPath(virDomainDiskDefPtr disk,
}
}
- for (tmp = disk->src; tmp; tmp = tmp->backingStore) {
+ for (tmp = disk->src; virStorageSourceIsBacking(tmp); tmp = tmp->backingStore) {
/* execute the callback only for local storage */
if (virStorageSourceIsLocalStorage(tmp) &&
tmp->path) {
diff --git a/src/conf/storage_conf.c b/src/conf/storage_conf.c
index 7c373e781..f808cd291 100644
--- a/src/conf/storage_conf.c
+++ b/src/conf/storage_conf.c
@@ -1169,7 +1169,8 @@ virStorageVolDefParseXML(virStoragePoolDefPtr pool,
if (virStorageSize(unit, capacity, &ret->target.capacity) < 0)
goto error;
} else if (!(flags & VIR_VOL_XML_PARSE_NO_CAPACITY) &&
- !((flags & VIR_VOL_XML_PARSE_OPT_CAPACITY) && ret->target.backingStore)) {
+ !((flags & VIR_VOL_XML_PARSE_OPT_CAPACITY) &&
+ virStorageSourceHasBacking(&ret->target))) {
virReportError(VIR_ERR_XML_ERROR, "%s", _("missing capacity element"));
goto error;
}
@@ -1497,7 +1498,7 @@ virStorageVolDefFormat(virStoragePoolDefPtr pool,
&def->target, "target") < 0)
goto cleanup;
- if (def->target.backingStore &&
+ if (virStorageSourceHasBacking(&def->target) &&
virStorageVolTargetDefFormat(options, &buf,
def->target.backingStore,
"backingStore") < 0)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 26c5ddb40..4d44c401b 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -2692,7 +2692,9 @@ virStorageSourceFindByNodeName;
virStorageSourceFree;
virStorageSourceGetActualType;
virStorageSourceGetSecurityLabelDef;
+virStorageSourceHasBacking;
virStorageSourceInitChainElement;
+virStorageSourceIsBacking;
virStorageSourceIsBlockLocal;
virStorageSourceIsEmpty;
virStorageSourceIsLocalStorage;
diff --git a/src/qemu/qemu_block.c b/src/qemu/qemu_block.c
index 8d232de3e..544b4893b 100644
--- a/src/qemu/qemu_block.c
+++ b/src/qemu/qemu_block.c
@@ -257,7 +257,7 @@ qemuBlockDiskClearDetectedNodes(virDomainDiskDefPtr disk)
{
virStorageSourcePtr next = disk->src;
- while (next) {
+ while (virStorageSourceIsBacking(next)) {
VIR_FREE(next->nodeformat);
VIR_FREE(next->nodestorage);
@@ -287,7 +287,7 @@ qemuBlockDiskDetectNodes(virDomainDiskDefPtr disk,
goto cleanup;
}
- while (src && entry) {
+ while (virStorageSourceIsBacking(src) && entry) {
if (src->nodeformat || src->nodestorage) {
if (STRNEQ_NULLABLE(src->nodeformat, entry->nodeformat) ||
STRNEQ_NULLABLE(src->nodestorage, entry->nodestorage))
diff --git a/src/qemu/qemu_cgroup.c b/src/qemu/qemu_cgroup.c
index 6fc413098..0f75e22f9 100644
--- a/src/qemu/qemu_cgroup.c
+++ b/src/qemu/qemu_cgroup.c
@@ -142,7 +142,7 @@ qemuSetupDiskCgroup(virDomainObjPtr vm,
virStorageSourcePtr next;
bool forceReadonly = false;
- for (next = disk->src; next; next = next->backingStore) {
+ for (next = disk->src; virStorageSourceIsBacking(next); next = next->backingStore) {
if (qemuSetupImageCgroupInternal(vm, next, forceReadonly) < 0)
return -1;
@@ -160,7 +160,7 @@ qemuTeardownDiskCgroup(virDomainObjPtr vm,
{
virStorageSourcePtr next;
- for (next = disk->src; next; next = next->backingStore) {
+ for (next = disk->src; virStorageSourceIsBacking(next); next = next->backingStore) {
if (qemuTeardownImageCgroup(vm, next) < 0)
return -1;
}
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index ed27a91fa..173fbca6e 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -5929,7 +5929,7 @@ qemuDomainDetermineDiskChain(virQEMUDriverPtr driver,
if (virStorageSourceIsEmpty(disk->src))
goto cleanup;
- if (disk->src->backingStore) {
+ if (virStorageSourceHasBacking(disk->src)) {
if (force_probe)
virStorageSourceBackingStoreClear(disk->src);
else
@@ -8548,7 +8548,7 @@ qemuDomainSetupDisk(virQEMUDriverConfigPtr cfg ATTRIBUTE_UNUSED,
char *dst = NULL;
int ret = -1;
- for (next = disk->src; next; next = next->backingStore) {
+ for (next = disk->src; virStorageSourceIsBacking(next); next = next->backingStore) {
if (!next->path || !virStorageSourceIsLocalStorage(next)) {
/* Not creating device. Just continue. */
continue;
@@ -9449,7 +9449,7 @@ qemuDomainNamespaceSetupDisk(virQEMUDriverPtr driver,
&ndevMountsPath) < 0)
goto cleanup;
- for (next = src; next; next = next->backingStore) {
+ for (next = src; virStorageSourceIsBacking(next); next = next->backingStore) {
if (virStorageSourceIsEmpty(next) ||
!virStorageSourceIsLocalStorage(next)) {
/* Not creating device. Just continue. */
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 0260c40ef..803df9f06 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -14448,7 +14448,7 @@ qemuDomainSnapshotUpdateDiskSourcesRenumber(virStorageSourcePtr src)
virStorageSourcePtr next;
unsigned int idx = 1;
- for (next = src->backingStore; next; next = next->backingStore)
+ for (next = src->backingStore; virStorageSourceIsBacking(next); next = next->backingStore)
next->id = idx++;
}
@@ -17048,7 +17048,7 @@ qemuDomainBlockCopyCommon(virDomainObjPtr vm,
}
/* clear the _SHALLOW flag if there is only one layer */
- if (!disk->src->backingStore)
+ if (!virStorageSourceHasBacking(disk->src))
flags &= ~VIR_DOMAIN_BLOCK_COPY_SHALLOW;
/* unless the user provides a pre-created file, shallow copy into a raw
@@ -17439,7 +17439,7 @@ qemuDomainBlockCommit(virDomainPtr dom,
goto endjob;
}
- if (!topSource->backingStore) {
+ if (!virStorageSourceHasBacking(topSource)) {
virReportError(VIR_ERR_INVALID_ARG,
_("top '%s' in chain for '%s' has no backing file"),
topSource->path, path);
@@ -19887,7 +19887,8 @@ qemuDomainGetStatsBlock(virQEMUDriverPtr driver,
virStorageSourcePtr src = disk->src;
unsigned int backing_idx = 0;
- while (src && (backing_idx == 0 || visitBacking)) {
+ while (virStorageSourceIsBacking(src) &&
+ (backing_idx == 0 || visitBacking)) {
if (qemuDomainGetStatsOneBlock(driver, cfg, dom, record, maxparams,
disk, src, visited, backing_idx,
stats, nodestats) < 0)
diff --git a/src/security/security_dac.c b/src/security/security_dac.c
index 349dbe81d..244b300a9 100644
--- a/src/security/security_dac.c
+++ b/src/security/security_dac.c
@@ -730,7 +730,7 @@ virSecurityDACSetDiskLabel(virSecurityManagerPtr mgr,
{
virStorageSourcePtr next;
- for (next = disk->src; next; next = next->backingStore) {
+ for (next = disk->src; virStorageSourceIsBacking(next); next = next->backingStore) {
if (virSecurityDACSetImageLabel(mgr, def, next) < 0)
return -1;
}
diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c
index 2e3082b7a..cd3e41193 100644
--- a/src/security/security_selinux.c
+++ b/src/security/security_selinux.c
@@ -1539,7 +1539,7 @@ virSecuritySELinuxRestoreImageLabelInt(virSecurityManagerPtr mgr,
* be tracked in domain XML, at which point labelskip should be a
* per-file attribute instead of a disk attribute. */
if (disk_seclabel && disk_seclabel->labelskip &&
- !src->backingStore)
+ !virStorageSourceHasBacking(src))
return 0;
/* Don't restore labels on readonly/shared disks, because other VMs may
@@ -1673,7 +1673,7 @@ virSecuritySELinuxSetDiskLabel(virSecurityManagerPtr mgr,
bool first = true;
virStorageSourcePtr next;
- for (next = disk->src; next; next = next->backingStore) {
+ for (next = disk->src; virStorageSourceIsBacking(next); next = next->backingStore) {
if (virSecuritySELinuxSetImageLabelInternal(mgr, def, next, first) < 0)
return -1;
diff --git a/src/security/virt-aa-helper.c b/src/security/virt-aa-helper.c
index 95906e68a..ef1bf0136 100644
--- a/src/security/virt-aa-helper.c
+++ b/src/security/virt-aa-helper.c
@@ -942,7 +942,7 @@ get_files(vahControl * ctl)
/* XXX - if we knew the qemu user:group here we could send it in
* so that the open could be re-tried as that user:group.
*/
- if (!disk->src->backingStore) {
+ if (!virStorageSourceHasBacking(disk->src)) {
bool probe = ctl->allowDiskFormatProbing;
virStorageFileGetMetadata(disk->src, -1, -1, probe, false);
}
diff --git a/src/storage/storage_backend_logical.c b/src/storage/storage_backend_logical.c
index 1e0f04e4e..a872a2f88 100644
--- a/src/storage/storage_backend_logical.c
+++ b/src/storage/storage_backend_logical.c
@@ -977,7 +977,7 @@ virStorageBackendLogicalCreateVol(virConnectPtr conn,
}
virCommandAddArgFormat(cmd, "%lluK", VIR_DIV_UP(vol->target.capacity,
1024));
- if (vol->target.backingStore)
+ if (virStorageSourceHasBacking(&vol->target))
virCommandAddArgList(cmd, "-s", vol->target.backingStore->path, NULL);
else
virCommandAddArg(cmd, def->source.name);
diff --git a/src/storage/storage_source.c b/src/storage/storage_source.c
index 864c69928..47b08f416 100644
--- a/src/storage/storage_source.c
+++ b/src/storage/storage_source.c
@@ -490,7 +490,7 @@ virStorageFileGetMetadataRecurse(virStorageSourcePtr src,
ret = 0;
cleanup:
- if (src->backingStore)
+ if (virStorageSourceHasBacking(src))
src->backingStore->id = depth;
VIR_FREE(buf);
virStorageFileDeinit(src);
diff --git a/src/storage/storage_util.c b/src/storage/storage_util.c
index a10e4590f..5252e429f 100644
--- a/src/storage/storage_util.c
+++ b/src/storage/storage_util.c
@@ -415,7 +415,7 @@ storageBackendCreateRaw(virConnectPtr conn ATTRIBUTE_UNUSED,
goto cleanup;
}
- if (vol->target.backingStore) {
+ if (virStorageSourceHasBacking(&vol->target)) {
virReportError(VIR_ERR_NO_SUPPORT, "%s",
_("backing storage not supported for raw volumes"));
goto cleanup;
@@ -722,7 +722,7 @@ storageBackendCreatePloop(virConnectPtr conn ATTRIBUTE_UNUSED,
return -1;
}
- if (vol->target.backingStore != NULL) {
+ if (virStorageSourceHasBacking(&vol->target)) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("copy-on-write ploop volumes are not yet supported"));
return -1;
@@ -1055,7 +1055,7 @@ storageBackendCreateQemuImgSetBacking(virStoragePoolObjPtr pool,
* backing store, not really sure what use it serves though, and it
* may cause issues with lvm. Untested essentially.
*/
- if (inputvol && inputvol->target.backingStore &&
+ if (inputvol && virStorageSourceHasBacking(&inputvol->target) &&
STRNEQ_NULLABLE(inputvol->target.backingStore->path,
info->backingPath)) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
@@ -1230,7 +1230,7 @@ virStorageBackendCreateQemuImgCmdFromVol(virConnectPtr conn,
storageBackendCreateQemuImgSetInput(inputvol, &info) < 0)
return NULL;
- if (vol->target.backingStore &&
+ if (virStorageSourceHasBacking(&vol->target) &&
storageBackendCreateQemuImgSetBacking(pool, vol, inputvol, &info) < 0)
return NULL;
@@ -1840,7 +1840,7 @@ virStorageBackendUpdateVolInfo(virStorageVolDefPtr vol,
openflags, readflags)) < 0)
return ret;
- if (vol->target.backingStore &&
+ if (virStorageSourceHasBacking(&vol->target) &&
(ret = storageBackendUpdateVolTargetInfo(VIR_STORAGE_VOL_FILE,
vol->target.backingStore,
withBlockVolFormat,
@@ -2035,7 +2035,7 @@ createFileDir(virConnectPtr conn ATTRIBUTE_UNUSED,
return -1;
}
- if (vol->target.backingStore) {
+ if (virStorageSourceHasBacking(&vol->target)) {
virReportError(VIR_ERR_NO_SUPPORT, "%s",
_("backing storage not supported for directories volumes"));
return -1;
@@ -3561,7 +3561,7 @@ virStorageBackendRefreshVolTargetUpdate(virStorageVolDefPtr vol)
if (vol->target.format == VIR_STORAGE_FILE_PLOOP)
vol->type = VIR_STORAGE_VOL_PLOOP;
- if (vol->target.backingStore) {
+ if (virStorageSourceHasBacking(&vol->target)) {
ignore_value(storageBackendUpdateVolTargetInfo(VIR_STORAGE_VOL_FILE,
vol->target.backingStore,
false,
diff --git a/src/util/virstoragefile.c b/src/util/virstoragefile.c
index 818a679de..93995a331 100644
--- a/src/util/virstoragefile.c
+++ b/src/util/virstoragefile.c
@@ -1292,7 +1292,7 @@ virStorageFileChainGetBroken(virStorageSourcePtr chain,
if (!chain)
return 0;
- for (tmp = chain; tmp; tmp = tmp->backingStore) {
+ for (tmp = chain; virStorageSourceIsBacking(tmp); tmp = tmp->backingStore) {
/* Break when we hit end of chain; report error if we detected
* a missing backing file, infinite loop, or other error */
if (!tmp->backingStore && tmp->backingStoreRaw) {
@@ -1566,6 +1566,33 @@ virStorageFileParseChainIndex(const char *diskTarget,
return ret;
}
+
+/**
+ * virStorageSourceIsBacking:
+ * @src: storage source
+ *
+ * Returns true if @src is a eligible backing store structure. Useful
+ * for iterators.
+ */
+bool
+virStorageSourceIsBacking(const virStorageSource *src)
+{
+ return !!src;
+}
+
+/**
+ * virStorageSourceHasBacking:
+ * @src: storage source
+ *
+ * Returns true if @src has backing store/chain.
+ */
+bool
+virStorageSourceHasBacking(const virStorageSource *src)
+{
+ return virStorageSourceIsBacking(src) && src->backingStore;
+}
+
+
/* Given a @chain, look for the backing store @name that is a backing file
* of @startFrom (or any member of @chain if @startFrom is NULL) and return
* that location within the chain. @chain must always point to the top of
@@ -1594,15 +1621,16 @@ virStorageFileChainLookup(virStorageSourcePtr chain,
*parent = NULL;
if (startFrom) {
- while (chain && chain != startFrom->backingStore)
+ while (virStorageSourceIsBacking(chain) &&
+ chain != startFrom->backingStore)
chain = chain->backingStore;
*parent = startFrom;
}
- while (chain) {
+ while (virStorageSourceIsBacking(chain)) {
if (!name && !idx) {
- if (!chain->backingStore)
+ if (!virStorageSourceHasBacking(chain))
break;
} else if (idx) {
VIR_DEBUG("%u: %s", chain->id, chain->path);
@@ -1640,7 +1668,7 @@ virStorageFileChainLookup(virStorageSourcePtr chain,
chain = chain->backingStore;
}
- if (!chain)
+ if (!virStorageSourceIsBacking(chain))
goto error;
return chain;
@@ -3854,7 +3882,7 @@ virStorageFileGetRelativeBackingPath(virStorageSourcePtr top,
*relpath = NULL;
- for (next = top; next; next = next->backingStore) {
+ for (next = top; virStorageSourceIsBacking(next); next = next->backingStore) {
if (!next->relPath) {
ret = 1;
goto cleanup;
@@ -3973,7 +4001,7 @@ virStorageSourceFindByNodeName(virStorageSourcePtr top,
if (idx)
*idx = 0;
- for (tmp = top; tmp; tmp = tmp->backingStore) {
+ for (tmp = top; virStorageSourceIsBacking(tmp); tmp = tmp->backingStore) {
if ((tmp->nodeformat && STREQ(tmp->nodeformat, nodeName)) ||
(tmp->nodestorage && STREQ(tmp->nodestorage, nodeName)))
return tmp;
diff --git a/src/util/virstoragefile.h b/src/util/virstoragefile.h
index d3bafefc3..86e60de2a 100644
--- a/src/util/virstoragefile.h
+++ b/src/util/virstoragefile.h
@@ -425,4 +425,10 @@ void
virStorageSourceNetworkAssignDefaultPorts(virStorageSourcePtr src)
ATTRIBUTE_NONNULL(1);
+bool
+virStorageSourceIsBacking(const virStorageSource *src);
+bool
+virStorageSourceHasBacking(const virStorageSource *src);
+
+
#endif /* __VIR_STORAGE_FILE_H__ */
diff --git a/tests/virstoragetest.c b/tests/virstoragetest.c
index ad4514871..35e97ff26 100644
--- a/tests/virstoragetest.c
+++ b/tests/virstoragetest.c
@@ -356,7 +356,7 @@ testStorageChain(const void *args)
}
elt = meta;
- while (elt) {
+ while (virStorageSourceIsBacking(elt)) {
char *expect = NULL;
char *actual = NULL;
--
2.14.1
--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
On 10/12/2017 02:07 PM, Peter Krempa wrote:
> Add a helper that will retrun true if a virStorageSource has backing
s/retrun/return/
> store. This will also aid in refactoring of the code further down.
> ---
The commit message mentions adding only one helper, but doesn't name it.
I like to mention new interfaces in commit messages, if only to make
grepping 'git log' for a particular interface more likely to hit the
relevant commits.
> +++ b/src/conf/domain_conf.c
> @@ -26607,7 +26607,7 @@ virDomainDiskDefForeachPath(virDomainDiskDefPtr disk,
> }
> }
>
> - for (tmp = disk->src; tmp; tmp = tmp->backingStore) {
> + for (tmp = disk->src; virStorageSourceIsBacking(tmp); tmp = tmp->backingStore) {
Here, you are adding a use of virStorageSourceIsBacking,
> /* execute the callback only for local storage */
> if (virStorageSourceIsLocalStorage(tmp) &&
> tmp->path) {
> diff --git a/src/conf/storage_conf.c b/src/conf/storage_conf.c
> index 7c373e781..f808cd291 100644
> --- a/src/conf/storage_conf.c
> +++ b/src/conf/storage_conf.c
> @@ -1169,7 +1169,8 @@ virStorageVolDefParseXML(virStoragePoolDefPtr pool,
> if (virStorageSize(unit, capacity, &ret->target.capacity) < 0)
> goto error;
> } else if (!(flags & VIR_VOL_XML_PARSE_NO_CAPACITY) &&
> - !((flags & VIR_VOL_XML_PARSE_OPT_CAPACITY) && ret->target.backingStore)) {
> + !((flags & VIR_VOL_XML_PARSE_OPT_CAPACITY) &&
> + virStorageSourceHasBacking(&ret->target))) {
and here, virStorageSourceHasBacking. So my immediate thought was
whether the 'Is' vs. 'Has' naming intentional? If so, you added two
interfaces, so the commit message needs a tweak.
> +++ b/src/libvirt_private.syms
> @@ -2692,7 +2692,9 @@ virStorageSourceFindByNodeName;
> virStorageSourceFree;
> virStorageSourceGetActualType;
> virStorageSourceGetSecurityLabelDef;
> +virStorageSourceHasBacking;
> virStorageSourceInitChainElement;
> +virStorageSourceIsBacking;
So you indeed are adding two interfaces, but it took me this far into
the review to know it.
One trick with git is that you can tell it to produce patches in a
particular order (see qemu's scripts/git.orderfile, for example); this
can be useful to hoist headers and build instructions first, showing the
new interfaces, prior to the .c files that change to use the new
interfaces, for a slightly faster review. But even with a preference of
.syms before .h before .c, I still find it helpful to do one-off
orderfile overrides; in this case, listing virstoragefile.c before other
.c files would also aid review.
> +++ b/src/qemu/qemu_cgroup.c
> @@ -160,7 +160,7 @@ qemuTeardownDiskCgroup(virDomainObjPtr vm,
> {
> virStorageSourcePtr next;
>
> - for (next = disk->src; next; next = next->backingStore) {
> + for (next = disk->src; virStorageSourceIsBacking(next); next = next->backingStore) {
Line longer than 80 columns; do we care?
> +++ b/src/util/virstoragefile.c
> @@ -1292,7 +1292,7 @@ virStorageFileChainGetBroken(virStorageSourcePtr chain,
> if (!chain)
> return 0;
>
> - for (tmp = chain; tmp; tmp = tmp->backingStore) {
> + for (tmp = chain; virStorageSourceIsBacking(tmp); tmp = tmp->backingStore) {
> /* Break when we hit end of chain; report error if we detected
> * a missing backing file, infinite loop, or other error */
> if (!tmp->backingStore && tmp->backingStoreRaw) {
> @@ -1566,6 +1566,33 @@ virStorageFileParseChainIndex(const char *diskTarget,
> return ret;
> }
>
> +
> +/**
> + * virStorageSourceIsBacking:
> + * @src: storage source
> + *
> + * Returns true if @src is a eligible backing store structure. Useful
> + * for iterators.
> + */
> +bool
> +virStorageSourceIsBacking(const virStorageSource *src)
> +{
> + return !!src;
> +}
> +
> +/**
> + * virStorageSourceHasBacking:
> + * @src: storage source
> + *
> + * Returns true if @src has backing store/chain.
> + */
> +bool
> +virStorageSourceHasBacking(const virStorageSource *src)
> +{
> + return virStorageSourceIsBacking(src) && src->backingStore;
> +}
The conversions look sane, and now you have an entry point for future
patches to tweak what constitutes a valid reference, without having to
hunt down all the iterations changed in this patch.
Looks like a reasonable refactoring, so in spite of my comments, I'm
fine with the code, and it is just the commit message that can be
improved, and/or the use of an order file to present things in an
altered order for ease of review.
Reviewed-by: Eric Blake <eblake@redhat.com>
--
Eric Blake, Principal Software Engineer
Red Hat, Inc. +1-919-301-3266
Virtualization: qemu.org | libvirt.org
--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
© 2016 - 2025 Red Hat, Inc.