[libvirt] [PATCH 0/5] Reject duplicate drive addresses
by Marc Hartmayer
Reject duplicate drive addresses at domain definition. Hot-plug for
disks and hostdevs is still to fix and this is why the old version of
drive address checking is still there. Additionally, it isn't that
easy to be sure that the changes won't break other drivers as these
are common code changes.
Marc Hartmayer (5):
conf: simplify functions virDomainSCSIDriveAddressIsUsedBy*()
conf: virDomainDriveAddressIsUsedByDisk: Rename type to bus_type
tests: don't use duplicate disk addresses
conf: add global check for duplicate drive addresses
tests: add test cases for address conflicts
src/conf/domain_conf.c | 184 +++++++++++++++++----
.../qemuxml2argv-disk-drive-address-conflict.xml | 27 +++
...xml2argv-disk-hostdev-scsi-address-conflict.xml | 30 ++++
...emuxml2argv-hostdevs-drive-address-conflict.xml | 33 ++++
.../qemuxml2argv-seclabel-dynamic-override.args | 4 +-
.../qemuxml2argv-seclabel-dynamic-override.xml | 2 +-
tests/qemuxml2argvtest.c | 8 +
.../qemuxml2xmlout-seclabel-dynamic-override.xml | 2 +-
8 files changed, 251 insertions(+), 39 deletions(-)
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-drive-address-conflict.xml
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-hostdev-scsi-address-conflict.xml
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-hostdevs-drive-address-conflict.xml
--
2.5.5
8 years
[libvirt] [PATCH v2 1/1] gluster: cache glfs connection object per volume
by prasanna.kalever@redhat.com
From: Prasanna Kumar Kalever <prasanna.kalever(a)redhat.com>
This patch optimizes calls to glfs_init() and friends
Currently, a start of a VM will call 2 glfs_new/glfs_init (which will create
glfs object, once for stat, read headers and next to chown) and then will fork
qemu process which will call once again (for actual read write IO).
Not that all, in case if we are have 4 extra attached disks, then the total
calls to glfs_init() and friends will be (4+1)*2 in libvirt and (4+1)*1 in
qemu space i.e 15 calls. Since we don't have control over qemu process as that
executes in a different process environment, lets do not bother much about it.
This patch shrinks these 10 calls (i.e objects from above example) to just
one, by maintaining a cache of glfs objects.
Additionally snapshot(external) scenario will further complex the situation ...
The glfs object is shared across other only if volume name and all the
volfile servers match (includes hostname, transport and port number).
In case of hit glfs object takes a ref and on close unref happens.
Thanks to 'Peter Krempa' for all the inputs.
Signed-off-by: Prasanna Kumar Kalever <prasanna.kalever(a)redhat.com>
---
v2: Address review comments from Peter on v1
* Rebased on latest master
* Changes to commit msg
* Introduce storage API's for Register and Unregister of volume
* During qemu process Start/Stop and snapshot create
* Check Transport and Port type
* Atomic element add/del to list and ref counting
Pending: Treating IP and FQDN belong to same host
v1: Initial patch
---
src/qemu/qemu_domain.c | 2 +-
src/qemu/qemu_domain.h | 5 +
src/qemu/qemu_driver.c | 29 ++++
src/qemu/qemu_process.c | 25 +++
src/storage/storage_backend_fs.c | 2 +
src/storage/storage_backend_gluster.c | 295 +++++++++++++++++++++++++++++++---
src/storage/storage_driver.c | 23 ++-
src/storage/storage_driver.h | 3 +
8 files changed, 357 insertions(+), 27 deletions(-)
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index 47332a8..35914c5 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -4837,7 +4837,7 @@ qemuDomainCleanupRun(virQEMUDriverPtr driver,
priv->ncleanupCallbacks_max = 0;
}
-static void
+void
qemuDomainGetImageIds(virQEMUDriverConfigPtr cfg,
virDomainObjPtr vm,
virStorageSourcePtr src,
diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
index 7650ff3..a9e38bd 100644
--- a/src/qemu/qemu_domain.h
+++ b/src/qemu/qemu_domain.h
@@ -591,6 +591,11 @@ bool qemuDomainDiskSourceDiffers(virDomainDiskDefPtr disk,
bool qemuDomainDiskChangeSupported(virDomainDiskDefPtr disk,
virDomainDiskDefPtr orig_disk);
+void qemuDomainGetImageIds(virQEMUDriverConfigPtr cfg,
+ virDomainObjPtr vm,
+ virStorageSourcePtr src,
+ uid_t *uid, gid_t *gid);
+
int qemuDomainStorageFileInit(virQEMUDriverPtr driver,
virDomainObjPtr vm,
virStorageSourcePtr src);
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 3517aa2..7cae094 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -14211,6 +14211,7 @@ qemuDomainSnapshotCreateSingleDiskActive(virQEMUDriverPtr driver,
cleanup:
if (need_unlink && virStorageFileUnlink(newDiskSrc))
VIR_WARN("unable to unlink just-created %s", source);
+ virStorageFileDeinit(disk->src);
virStorageFileDeinit(newDiskSrc);
virStorageSourceFree(newDiskSrc);
virStorageSourceFree(persistDiskSrc);
@@ -14566,6 +14567,7 @@ qemuDomainSnapshotCreateXML(virDomainPtr domain,
virDomainSnapshotObjPtr snap = NULL;
virDomainSnapshotPtr snapshot = NULL;
virDomainSnapshotDefPtr def = NULL;
+ virDomainSnapshotDefPtr refDef = NULL;
bool update_current = true;
bool redefine = flags & VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE;
unsigned int parse_flags = VIR_DOMAIN_SNAPSHOT_PARSE_DISKS;
@@ -14574,6 +14576,9 @@ qemuDomainSnapshotCreateXML(virDomainPtr domain,
bool align_match = true;
virQEMUDriverConfigPtr cfg = NULL;
virCapsPtr caps = NULL;
+ unsigned int dIndex;
+ uid_t uid;
+ gid_t gid;
virCheckFlags(VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE |
VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT |
@@ -14690,6 +14695,19 @@ qemuDomainSnapshotCreateXML(virDomainPtr domain,
qemuDomainObjSetAsyncJobMask(vm, QEMU_JOB_NONE);
+ for (dIndex = 0; dIndex < def->ndisks; dIndex++) {
+ virDomainSnapshotDiskDef disk = def->disks[dIndex];
+
+ if (virStorageSourceIsEmpty(disk.src))
+ continue;
+
+ qemuDomainGetImageIds(cfg, vm, disk.src, &uid, &gid);
+
+ if (virStorageVolumeRegister(disk.src, uid, gid) <0)
+ goto cleanup;
+ }
+
+
if (redefine) {
if (virDomainSnapshotRedefinePrep(domain, vm, &def, &snap,
&update_current, flags) < 0)
@@ -14800,6 +14818,17 @@ qemuDomainSnapshotCreateXML(virDomainPtr domain,
snapshot = virGetDomainSnapshot(domain, snap->def->name);
endjob:
+ refDef = (!snap) ? def : snap->def;
+
+ for (dIndex = 0; dIndex < refDef->ndisks; dIndex++) {
+ virDomainSnapshotDiskDef disk = refDef->disks[dIndex];
+
+ if (virStorageSourceIsEmpty(disk.src))
+ continue;
+
+ virStorageVolumeUnRegister(disk.src);
+ }
+
if (snapshot && !(flags & VIR_DOMAIN_SNAPSHOT_CREATE_NO_METADATA)) {
if (qemuDomainSnapshotWriteMetadata(vm, snap, driver->caps,
cfg->snapshotDir) < 0) {
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index ecd7ded..20793cf 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -4612,6 +4612,9 @@ qemuProcessInit(virQEMUDriverPtr driver,
qemuDomainObjPrivatePtr priv = vm->privateData;
int stopFlags;
int ret = -1;
+ unsigned int dIndex;
+ uid_t uid;
+ gid_t gid;
VIR_DEBUG("vm=%p name=%s id=%d migration=%d",
vm, vm->def->name, vm->def->id, migration);
@@ -4664,6 +4667,18 @@ qemuProcessInit(virQEMUDriverPtr driver,
if (qemuDomainSetPrivatePaths(driver, vm) < 0)
goto cleanup;
+ for (dIndex = 0; dIndex < vm->def->ndisks; dIndex++) {
+ virDomainDiskDefPtr disk = vm->def->disks[dIndex];
+
+ if (virStorageSourceIsEmpty(disk->src))
+ continue;
+
+ qemuDomainGetImageIds(cfg, vm, disk->src, &uid, &gid);
+
+ if (virStorageVolumeRegister(disk->src, uid, gid) < 0)
+ goto cleanup;
+ }
+
ret = 0;
cleanup:
@@ -5671,6 +5686,7 @@ qemuProcessFinishStartup(virConnectPtr conn,
{
virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
int ret = -1;
+ unsigned int dIndex;
if (startCPUs) {
VIR_DEBUG("Starting domain CPUs");
@@ -5695,6 +5711,15 @@ qemuProcessFinishStartup(virConnectPtr conn,
VIR_HOOK_SUBOP_BEGIN) < 0)
goto cleanup;
+ for (dIndex = 0; dIndex < vm->def->ndisks; dIndex++) {
+ virDomainDiskDefPtr disk = vm->def->disks[dIndex];
+
+ if (virStorageSourceIsEmpty(disk->src))
+ continue;
+
+ virStorageVolumeUnRegister(disk->src);
+ }
+
ret = 0;
cleanup:
diff --git a/src/storage/storage_backend_fs.c b/src/storage/storage_backend_fs.c
index de0e8d5..0e03e06 100644
--- a/src/storage/storage_backend_fs.c
+++ b/src/storage/storage_backend_fs.c
@@ -1488,6 +1488,8 @@ virStorageFileBackendFileDeinit(virStorageSourcePtr src)
VIR_FREE(priv->canonpath);
VIR_FREE(priv);
+
+ VIR_FREE(src->drv);
}
diff --git a/src/storage/storage_backend_gluster.c b/src/storage/storage_backend_gluster.c
index 8e86704..18b7fc3 100644
--- a/src/storage/storage_backend_gluster.c
+++ b/src/storage/storage_backend_gluster.c
@@ -31,11 +31,34 @@
#include "virstoragefile.h"
#include "virstring.h"
#include "viruri.h"
+#include "viratomic.h"
#define VIR_FROM_THIS VIR_FROM_STORAGE
VIR_LOG_INIT("storage.storage_backend_gluster");
+static bool virGlusterGlobalError;
+static virOnceControl glusterConnOnce = VIR_ONCE_CONTROL_INITIALIZER;
+
+typedef struct _virStorageBackendGlusterState virStorageBackendGlusterState;
+typedef virStorageBackendGlusterState *virStorageBackendGlusterStatePtr;
+
+typedef struct _virStorageFileBackendGlusterPriv virStorageFileBackendGlusterPriv;
+typedef virStorageFileBackendGlusterPriv *virStorageFileBackendGlusterPrivPtr;
+
+typedef struct _unixSocketAddress unixSocketAddress;
+
+typedef struct _inetSocketAddress inetSocketAddress;
+
+typedef struct _glusterServer glusterServer;
+typedef struct _glusterServer *glusterServerPtr;
+
+typedef struct _virStorageBackendGlusterStatePreopened virStorageBackendGlusterStatePreopened;
+typedef virStorageBackendGlusterStatePreopened *virStorageBackendGlusterStatePtrPreopened;
+
+typedef struct _virStorageBackendGlusterconnCache virStorageBackendGlusterconnCache;
+typedef virStorageBackendGlusterconnCache *virStorageBackendGlusterconnCachePtr;
+
struct _virStorageBackendGlusterState {
glfs_t *vol;
@@ -47,8 +70,241 @@ struct _virStorageBackendGlusterState {
char *dir; /* dir from URI, or "/"; always starts and ends in '/' */
};
-typedef struct _virStorageBackendGlusterState virStorageBackendGlusterState;
-typedef virStorageBackendGlusterState *virStorageBackendGlusterStatePtr;
+struct _virStorageFileBackendGlusterPriv {
+ glfs_t *vol;
+ char *canonpath;
+};
+
+struct _unixSocketAddress {
+ char *path;
+};
+
+struct _inetSocketAddress {
+ char *host;
+ char *port;
+};
+
+struct _glusterServer {
+ virStorageNetHostTransport type;
+ union { /* union tag is @type */
+ unixSocketAddress uds;
+ inetSocketAddress tcp;
+ } u;
+};
+
+struct _virStorageBackendGlusterStatePreopened {
+ virStorageFileBackendGlusterPrivPtr priv;
+ unsigned int nservers;
+ glusterServerPtr *hosts;
+ char *volname;
+ volatile int ref;
+};
+
+struct _virStorageBackendGlusterconnCache {
+ virMutex lock;
+ size_t nConn;
+ virStorageBackendGlusterStatePtrPreopened *conn;
+};
+
+virStorageBackendGlusterconnCachePtr connCache = {0,};
+
+
+static void
+virGlusterConnAlloc(void)
+{
+ if ((VIR_ALLOC(connCache) < 0))
+ virGlusterGlobalError = false;
+}
+
+static int
+virStorageBackendGlusterSetPreopened(virStorageSourcePtr src,
+ virStorageFileBackendGlusterPrivPtr priv)
+{
+ unsigned int idx;
+ virStorageBackendGlusterStatePtrPreopened entry = NULL;
+
+ if (connCache == NULL && (virOnce(&glusterConnOnce,
+ virGlusterConnAlloc) < 0))
+ return -1;
+
+ if (virGlusterGlobalError)
+ return -1;
+
+ if (!connCache->nConn) {
+ if (virMutexInit(&connCache->lock) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Unable to initialize mutex"));
+ return -1;
+ }
+ }
+
+ for (idx = 0; idx < connCache->nConn; idx++) {
+ if (STREQ(connCache->conn[idx]->volname, src->volume))
+ return 0;
+ }
+
+ if (VIR_ALLOC(entry) < 0)
+ return -1;
+
+ if (VIR_STRDUP(entry->volname, src->volume) < 0)
+ goto error;
+
+ if (VIR_ALLOC_N(entry->hosts, entry->nservers) < 0)
+ goto error;
+
+ entry->nservers = src->nhosts;
+
+ for (idx = 0; idx < src->nhosts; idx++) {
+ if (VIR_ALLOC(entry->hosts[idx]) < 0)
+ goto error;
+ if (src->hosts[idx].transport == VIR_STORAGE_NET_HOST_TRANS_UNIX) {
+ if (VIR_STRDUP(entry->hosts[idx]->u.uds.path,
+ src->hosts[idx].socket) < 0)
+ goto error;
+ entry->hosts[idx]->type = VIR_STORAGE_NET_HOST_TRANS_UNIX;
+ } else if (src->hosts[idx].transport ==
+ VIR_STORAGE_NET_HOST_TRANS_TCP) {
+ if (VIR_STRDUP(entry->hosts[idx]->u.tcp.host,
+ src->hosts[idx].name) < 0)
+ goto error;
+ if (VIR_STRDUP(entry->hosts[idx]->u.tcp.port,
+ src->hosts[idx].port) < 0)
+ goto error;
+ entry->hosts[idx]->type = VIR_STORAGE_NET_HOST_TRANS_TCP;
+ } else {
+ entry->hosts[idx]->type = VIR_STORAGE_NET_HOST_TRANS_LAST;
+ }
+ }
+ entry->priv = priv;
+
+ virMutexLock(&connCache->lock);
+ virAtomicIntSet(&entry->ref, 1);
+ if (VIR_INSERT_ELEMENT(connCache->conn, -1, connCache->nConn, entry) < 0) {
+ virMutexUnlock(&connCache->lock);
+ goto error;
+ }
+ virMutexUnlock(&connCache->lock);
+
+ return 0;
+
+ error:
+ for (idx = 0; idx < entry->nservers; idx++) {
+ if (entry->hosts[idx]->type == VIR_STORAGE_NET_HOST_TRANS_UNIX) {
+ VIR_FREE(entry->hosts[idx]->u.uds.path);
+ } else {
+ VIR_FREE(entry->hosts[idx]->u.tcp.host);
+ VIR_FREE(entry->hosts[idx]->u.tcp.port);
+ }
+ VIR_FREE(entry->hosts[idx]);
+ }
+
+ VIR_FREE(entry->hosts);
+ VIR_FREE(entry->volname);
+ VIR_FREE(entry);
+
+ return -1;
+}
+
+static glfs_t *
+virStorageBackendGlusterFindPreopened(virStorageSourcePtr src)
+{
+ unsigned int cIdx, sIdx, nIdx; /* connectionIdx, savedIdx, newIdx */
+ bool flag = false;
+
+ if (connCache == NULL)
+ return NULL;
+
+ virStorageBackendGlusterStatePtrPreopened entry;
+
+ for (cIdx = 0; cIdx < connCache->nConn; cIdx++) {
+ entry = connCache->conn[cIdx];
+ if (STREQ(entry->volname, src->volume)) {
+ if (entry->nservers == src->nhosts) {
+ for (sIdx = 0; sIdx < entry->nservers; sIdx++) {
+ for (nIdx = 0; nIdx < src->nhosts; nIdx++) {
+ if (entry->hosts[sIdx]->type ==
+ src->hosts[nIdx].transport) {
+ if (entry->hosts[sIdx]->type
+ == VIR_STORAGE_NET_HOST_TRANS_UNIX) {
+ if (STREQ(entry->hosts[sIdx]->u.uds.path,
+ src->hosts[nIdx].socket)) {
+ flag = true;
+ break;
+ }
+ } else {
+ if (STREQ(entry->hosts[sIdx]->u.tcp.host,
+ src->hosts[nIdx].name) &&
+ STREQ(entry->hosts[sIdx]->u.tcp.port,
+ src->hosts[nIdx].port)) {
+ flag = true;
+ break;
+ }
+ }
+ }
+ }
+ if (!flag)
+ return NULL;
+ flag = false;
+ }
+ virAtomicIntInc(&entry->ref);
+ return entry->priv->vol;
+ } else {
+ return NULL;
+ }
+ }
+ }
+ return NULL;
+}
+
+static void
+virStorageBackendGlusterClosePreopened(virStorageSourcePtr src)
+{
+ virStorageFileBackendGlusterPrivPtr priv = src->drv->priv;
+ unsigned int cIdx, hIdx; /* connectionIdx, hostIdx */
+
+ for (cIdx = 0; cIdx < connCache->nConn; cIdx++) {
+ if (STREQ(connCache->conn[cIdx]->volname, src->volume)) {
+ virAtomicIntDecAndTest(&connCache->conn[cIdx]->ref);
+ if (virAtomicIntGet(&connCache->conn[cIdx]->ref) != 0) {
+ if (priv && priv->canonpath) {
+ VIR_FREE(priv->canonpath);
+ VIR_FREE(priv);
+ src->drv->priv = NULL;
+ }
+ return;
+ }
+
+ glfs_fini(connCache->conn[cIdx]->priv->vol);
+
+ VIR_FREE(connCache->conn[cIdx]->priv->canonpath);
+ VIR_FREE(connCache->conn[cIdx]->priv);
+
+ for (hIdx = 0; hIdx < connCache->conn[cIdx]->nservers; hIdx++) {
+ if (connCache->conn[cIdx]->hosts[hIdx]->type ==
+ VIR_STORAGE_NET_HOST_TRANS_UNIX) {
+ VIR_FREE(connCache->conn[cIdx]->hosts[hIdx]->u.uds.path);
+ } else {
+ VIR_FREE(connCache->conn[cIdx]->hosts[hIdx]->u.tcp.host);
+ VIR_FREE(connCache->conn[cIdx]->hosts[hIdx]->u.tcp.port);
+ }
+ VIR_FREE(connCache->conn[cIdx]->hosts[hIdx]);
+ }
+
+ VIR_FREE(connCache->conn[cIdx]->hosts);
+ VIR_FREE(connCache->conn[cIdx]->volname);
+ VIR_FREE(connCache->conn[cIdx]);
+
+ virMutexLock(&connCache->lock);
+ VIR_DELETE_ELEMENT(connCache->conn, cIdx, connCache->nConn);
+ virMutexUnlock(&connCache->lock);
+
+ VIR_FREE(src->drv);
+ }
+ }
+
+ if (!connCache->conn)
+ virMutexDestroy(&connCache->lock);
+}
static void
virStorageBackendGlusterClose(virStorageBackendGlusterStatePtr state)
@@ -538,30 +794,14 @@ virStorageBackend virStorageBackendGluster = {
};
-typedef struct _virStorageFileBackendGlusterPriv virStorageFileBackendGlusterPriv;
-typedef virStorageFileBackendGlusterPriv *virStorageFileBackendGlusterPrivPtr;
-
-struct _virStorageFileBackendGlusterPriv {
- glfs_t *vol;
- char *canonpath;
-};
-
-
static void
virStorageFileBackendGlusterDeinit(virStorageSourcePtr src)
{
- virStorageFileBackendGlusterPrivPtr priv = src->drv->priv;
-
VIR_DEBUG("deinitializing gluster storage file %p (gluster://%s:%s/%s%s)",
src, src->hosts->name, src->hosts->port ? src->hosts->port : "0",
src->volume, src->path);
- if (priv->vol)
- glfs_fini(priv->vol);
- VIR_FREE(priv->canonpath);
-
- VIR_FREE(priv);
- src->drv->priv = NULL;
+ virStorageBackendGlusterClosePreopened(src);
}
static int
@@ -612,6 +852,7 @@ virStorageFileBackendGlusterInitServer(virStorageFileBackendGlusterPrivPtr priv,
static int
virStorageFileBackendGlusterInit(virStorageSourcePtr src)
{
+ int ret = 0;
virStorageFileBackendGlusterPrivPtr priv = NULL;
size_t i;
@@ -625,6 +866,12 @@ virStorageFileBackendGlusterInit(virStorageSourcePtr src)
if (VIR_ALLOC(priv) < 0)
return -1;
+ priv->vol = virStorageBackendGlusterFindPreopened(src);
+ if (priv->vol) {
+ src->drv->priv = priv;
+ return ret;
+ }
+
VIR_DEBUG("initializing gluster storage file %p "
"(priv='%p' volume='%s' path='%s') as [%u:%u]",
src, priv, src->volume, src->path,
@@ -635,6 +882,10 @@ virStorageFileBackendGlusterInit(virStorageSourcePtr src)
goto error;
}
+ ret = virStorageBackendGlusterSetPreopened(src, priv);
+ if (ret < 0)
+ goto error;
+
for (i = 0; i < src->nhosts; i++) {
if (virStorageFileBackendGlusterInitServer(priv, src->hosts + i) < 0)
goto error;
@@ -648,13 +899,13 @@ virStorageFileBackendGlusterInit(virStorageSourcePtr src)
}
src->drv->priv = priv;
+ ret = 0;
- return 0;
+ return ret;
error:
- if (priv->vol)
- glfs_fini(priv->vol);
VIR_FREE(priv);
+ virStorageBackendGlusterClosePreopened(src);
return -1;
}
diff --git a/src/storage/storage_driver.c b/src/storage/storage_driver.c
index df65807..9c3bffb 100644
--- a/src/storage/storage_driver.c
+++ b/src/storage/storage_driver.c
@@ -2900,11 +2900,8 @@ virStorageFileDeinit(virStorageSourcePtr src)
if (!virStorageFileIsInitialized(src))
return;
- if (src->drv->backend &&
- src->drv->backend->backendDeinit)
+ if (src->drv->backend && src->drv->backend->backendDeinit)
src->drv->backend->backendDeinit(src);
-
- VIR_FREE(src->drv);
}
@@ -2967,6 +2964,24 @@ virStorageFileInit(virStorageSourcePtr src)
return virStorageFileInitAs(src, -1, -1);
}
+int
+virStorageVolumeRegister(virStorageSourcePtr src,
+ uid_t uid, gid_t gid)
+{
+ if (virStorageFileInitAs(src, uid, gid) < 0)
+ return -1;
+
+ src->drv->priv = NULL;
+
+ return 0;
+}
+
+void
+virStorageVolumeUnRegister(virStorageSourcePtr src)
+{
+ virStorageFileDeinit(src);
+}
+
/**
* virStorageFileCreate: Creates an empty storage file via storage driver
diff --git a/src/storage/storage_driver.h b/src/storage/storage_driver.h
index 3f2549d..89a3d55 100644
--- a/src/storage/storage_driver.h
+++ b/src/storage/storage_driver.h
@@ -71,4 +71,7 @@ char *virStoragePoolObjBuildTempFilePath(virStoragePoolObjPtr pool,
int storageRegister(void);
+int virStorageVolumeRegister(virStorageSourcePtr src, uid_t uid, gid_t gid);
+void virStorageVolumeUnRegister(virStorageSourcePtr src);
+
#endif /* __VIR_STORAGE_DRIVER_H__ */
--
2.7.4
8 years
[libvirt] [PATCH] docs: add "more PCIe less legacy PCI" to list of new features
by Laine Stump
---
If this entry looks okay and I'm not around on IRC, feel free to push
it so it will be in RC2.
docs/news.html.in | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/docs/news.html.in b/docs/news.html.in
index 8a86dd4..df245ea 100644
--- a/docs/news.html.in
+++ b/docs/news.html.in
@@ -39,6 +39,14 @@
can be specified without providing a base address, which simplifies
user configuration
</li>
+ <li>qemu: for machinetypes that use a PCI Express root bus
+ (e.g. x86_64/Q35 and aarch64/virt), any unaddressed PCI
+ device that is an Express device (all virtio-1.0 devices,
+ e1000e, nec-xhci, vfio assigned devices) will be placed on
+ an Express controller (i.e. a pcie-root-port) instead of a
+ legacy PCI controller (i.e. pci-bridge). pcie-root-ports are
+ automatically added as needed.
+ </li>
</ul>
</li>
<li><strong>Improvements</strong>
--
2.7.4
8 years, 1 month
[libvirt] Entering freeze for 2.5.0
by Daniel Veillard
With exception of the patch set of Laine which we will likely push
in today or tomorrow. I have made the signed tarball and rpms available
at the usual place:
ftp://libvirt.org/libvirt/
and also tagged the RC1 in git.
This seems to work fine with my minimal testing, but obviously others
should give it a try and try it in more diverse environments.
If all goes well, I will push an rc2 on Thursday and plan the final
release over the w.e.
thanks for givit it a try,
Daniel
--
Daniel Veillard | Open Source and Standards, Red Hat
veillard(a)redhat.com | libxml Gnome XML XSLT toolkit http://xmlsoft.org/
http://veillard.com/ | virtualization library http://libvirt.org/
8 years, 1 month
[libvirt] Plan for next release(s)
by Daniel Veillard
I'm late <grin/> so I think that if we don't want to slip too much
the best would be to enter freeze tomorrow (Tuesday) then have RC2
around Thursday and a release over the week-end.
That said they are supposed to mess with my internet tomorrow morning
and I'm travelling till the end of the week, but the above plan should
be doable. Hope that's okay with everybody.
Then usually December is a low productivity month, and Feb is short,
so it is tempting to do like for previous years i.e. release mid-january
and end of Feb, except the Jan release will be 3.0.0.
Works for everybody ?
Daniel
--
Daniel Veillard | Open Source and Standards, Red Hat
veillard(a)redhat.com | libxml Gnome XML XSLT toolkit http://xmlsoft.org/
http://veillard.com/ | virtualization library http://libvirt.org/
8 years, 1 month
[libvirt] [PATCH 0/8] Make NSS module lookup by libvirt domain names too
by Michal Privoznik
So far, the NSS module relies on guests providing hostnames
during DHCP transaction, because if they do it's recorded in a
json file that NSS module consults when doing the hostname
translation. But there are few cases where this is not enough:
some system (e.g. old RHEL6) don't provide hostname at all.
If that's the case we can maintain a separate file $bridge.macs
where we would keep a list of pairs <domain, mac address list>.
Thus next time when doing hostname translation we can look up MAC
address list for given domain, and then lookup the MAC <-> IP
mapping in $bridge.status. It's a bit clunky, but it's our best
shot.
Michal Privoznik (8):
network: Don't unlock non-locked network driver
nssmock: Prefer free() over VIR_FREE()
virstring: Introduce virStringListAdd
virstring: Introduce virStringListRemove
util: Introduce virFileRewriteStr
util: Introduce virMACMap module
network: Track MAC address map
nss: Lookup by libvirt domain names too
cfg.mk | 2 +-
docs/nss.html.in | 13 +-
po/POTFILES.in | 1 +
src/Makefile.am | 9 +
src/conf/network_conf.h | 4 +
src/conf/virsecretobj.c | 20 +-
src/libvirt_private.syms | 12 ++
src/network/bridge_driver.c | 95 ++++++++-
src/network/leaseshelper.c | 14 +-
src/util/virfile.c | 24 ++-
src/util/virfile.h | 7 +-
src/util/virmacmap.c | 399 +++++++++++++++++++++++++++++++++++
src/util/virmacmap.h | 48 +++++
src/util/virstring.c | 87 ++++++++
src/util/virstring.h | 6 +
src/util/virxml.c | 4 +-
tests/Makefile.am | 14 ++
tests/nssdata/virbr0.macs | 23 ++
tests/nssdata/virbr0.status | 5 +
tests/nssdata/virbr1.macs | 21 ++
tests/nssdata/virbr1.status | 5 +
tests/nssmock.c | 25 ++-
tests/nsstest.c | 2 +
tests/virmacmapmock.c | 29 +++
tests/virmacmaptest.c | 232 ++++++++++++++++++++
tests/virmacmaptestdata/complex.json | 45 ++++
tests/virmacmaptestdata/empty.json | 3 +
tests/virmacmaptestdata/simple.json | 8 +
tests/virmacmaptestdata/simple2.json | 16 ++
tests/virstringtest.c | 80 +++++++
tools/nss/libvirt_nss.c | 173 +++++++++++----
31 files changed, 1340 insertions(+), 86 deletions(-)
create mode 100644 src/util/virmacmap.c
create mode 100644 src/util/virmacmap.h
create mode 100644 tests/nssdata/virbr0.macs
create mode 100644 tests/nssdata/virbr1.macs
create mode 100644 tests/virmacmapmock.c
create mode 100644 tests/virmacmaptest.c
create mode 100644 tests/virmacmaptestdata/complex.json
create mode 100644 tests/virmacmaptestdata/empty.json
create mode 100644 tests/virmacmaptestdata/simple.json
create mode 100644 tests/virmacmaptestdata/simple2.json
--
2.8.4
8 years, 1 month
[libvirt] [PATCH] xen: Fix build when with xen disabled and libxl enabled
by Peter Krempa
xen_common.c does not get compiled in such case which breaks the build
due to xenDomainDefAddImplicitInputDevice not being available.
Move the function to a different place to resolve the issue. Caused by
commit 36785c7e
---
src/Makefile.am | 4 ++--
src/conf/domain_conf.c | 22 ++++++++++++++++++++++
src/conf/domain_conf.h | 3 +++
src/libxl/libxl_domain.c | 3 +--
src/xen/xen_driver.c | 2 +-
src/xenapi/xenapi_driver.c | 3 +--
src/xenconfig/xen_common.c | 22 ----------------------
src/xenconfig/xen_common.h | 3 ---
8 files changed, 30 insertions(+), 32 deletions(-)
diff --git a/src/Makefile.am b/src/Makefile.am
index d440548..eaf7b59 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1250,7 +1250,7 @@ libvirt_driver_xen_impl_la_CFLAGS = \
-I$(srcdir)/xenconfig \
$(AM_CFLAGS)
libvirt_driver_xen_impl_la_LDFLAGS = $(AM_LDFLAGS)
-libvirt_driver_xen_impl_la_LIBADD = $(XEN_LIBS) libvirt_xenconfig.la
+libvirt_driver_xen_impl_la_LIBADD = $(XEN_LIBS)
libvirt_driver_xen_impl_la_SOURCES = $(XEN_DRIVER_SOURCES)
endif WITH_XEN
@@ -1311,7 +1311,7 @@ if WITH_XENAPI
noinst_LTLIBRARIES += libvirt_driver_xenapi.la
libvirt_la_BUILT_LIBADD += libvirt_driver_xenapi.la
libvirt_driver_xenapi_la_CFLAGS = $(LIBXENSERVER_CFLAGS) $(CURL_CFLAGS) \
- -I$(srcdir)/conf -I$(srcdir)/xenconfig $(AM_CFLAGS)
+ -I$(srcdir)/conf $(AM_CFLAGS)
libvirt_driver_xenapi_la_LDFLAGS = $(AM_LDFLAGS)
libvirt_driver_xenapi_la_LIBADD = $(LIBXENSERVER_LIBS) $(CURL_LIBS)
libvirt_driver_xenapi_la_SOURCES = $(XENAPI_DRIVER_SOURCES)
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index b001efc..64665fa 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -25786,3 +25786,25 @@ virDomainDefVcpuOrderClear(virDomainDefPtr def)
for (i = 0; i < def->maxvcpus; i++)
def->vcpus[i]->order = 0;
}
+
+
+int
+virDomainDefXenAddImplicitInputDevice(virDomainDefPtr def)
+{
+ virDomainInputBus implicitInputBus = VIR_DOMAIN_INPUT_BUS_XEN;
+
+ if (def->os.type == VIR_DOMAIN_OSTYPE_HVM)
+ implicitInputBus = VIR_DOMAIN_INPUT_BUS_PS2;
+
+ if (virDomainDefMaybeAddInput(def,
+ VIR_DOMAIN_INPUT_TYPE_MOUSE,
+ implicitInputBus) < 0)
+ return -1;
+
+ if (virDomainDefMaybeAddInput(def,
+ VIR_DOMAIN_INPUT_TYPE_KBD,
+ implicitInputBus) < 0)
+ return -1;
+
+ return 0;
+}
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 4447b03..00e833d 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -3211,4 +3211,7 @@ virDomainGetBlkioParametersAssignFromDef(virDomainDefPtr def,
virTypedParameterPtr params,
int *nparams,
int maxparams);
+
+int virDomainDefXenAddImplicitInputDevice(virDomainDefPtr def);
+
#endif /* __DOMAIN_CONF_H */
diff --git a/src/libxl/libxl_domain.c b/src/libxl/libxl_domain.c
index 5cde576..557a408 100644
--- a/src/libxl/libxl_domain.c
+++ b/src/libxl/libxl_domain.c
@@ -37,7 +37,6 @@
#include "virstring.h"
#include "virtime.h"
#include "locking/domain_lock.h"
-#include "xen_common.h"
#include "network/bridge_driver.h"
#define VIR_FROM_THIS VIR_FROM_LIBXL
@@ -407,7 +406,7 @@ libxlDomainDefPostParse(virDomainDefPtr def,
}
/* add implicit input devices */
- if (xenDomainDefAddImplicitInputDevice(def) < 0)
+ if (virDomainDefXenAddImplicitInputDevice(def) < 0)
return -1;
return 0;
diff --git a/src/xen/xen_driver.c b/src/xen/xen_driver.c
index 3f9bfa7..55c3eb4 100644
--- a/src/xen/xen_driver.c
+++ b/src/xen/xen_driver.c
@@ -384,7 +384,7 @@ xenDomainDefPostParse(virDomainDefPtr def,
}
/* add implicit input device */
- if (xenDomainDefAddImplicitInputDevice(def) <0)
+ if (virDomainDefXenAddImplicitInputDevice(def) <0)
return -1;
return 0;
diff --git a/src/xenapi/xenapi_driver.c b/src/xenapi/xenapi_driver.c
index a9ed407..0949192 100644
--- a/src/xenapi/xenapi_driver.c
+++ b/src/xenapi/xenapi_driver.c
@@ -39,7 +39,6 @@
#include "xenapi_driver_private.h"
#include "xenapi_utils.h"
#include "virstring.h"
-#include "xen_common.h"
#define VIR_FROM_THIS VIR_FROM_XENAPI
@@ -80,7 +79,7 @@ xenapiDomainDefPostParse(virDomainDefPtr def,
void *parseOpaque ATTRIBUTE_UNUSED)
{
/* add implicit input device */
- if (xenDomainDefAddImplicitInputDevice(def) < 0)
+ if (virDomainDefXenAddImplicitInputDevice(def) < 0)
return -1;
return 0;
diff --git a/src/xenconfig/xen_common.c b/src/xenconfig/xen_common.c
index 7968d40..b129f5e 100644
--- a/src/xenconfig/xen_common.c
+++ b/src/xenconfig/xen_common.c
@@ -1870,25 +1870,3 @@ xenFormatConfigCommon(virConfPtr conf,
return 0;
}
-
-
-int
-xenDomainDefAddImplicitInputDevice(virDomainDefPtr def)
-{
- virDomainInputBus implicitInputBus = VIR_DOMAIN_INPUT_BUS_XEN;
-
- if (def->os.type == VIR_DOMAIN_OSTYPE_HVM)
- implicitInputBus = VIR_DOMAIN_INPUT_BUS_PS2;
-
- if (virDomainDefMaybeAddInput(def,
- VIR_DOMAIN_INPUT_TYPE_MOUSE,
- implicitInputBus) < 0)
- return -1;
-
- if (virDomainDefMaybeAddInput(def,
- VIR_DOMAIN_INPUT_TYPE_KBD,
- implicitInputBus) < 0)
- return -1;
-
- return 0;
-}
diff --git a/src/xenconfig/xen_common.h b/src/xenconfig/xen_common.h
index 9055692..de981ba 100644
--- a/src/xenconfig/xen_common.h
+++ b/src/xenconfig/xen_common.h
@@ -67,7 +67,4 @@ int xenFormatConfigCommon(virConfPtr conf,
virConnectPtr conn,
const char *nativeFormat);
-
-int xenDomainDefAddImplicitInputDevice(virDomainDefPtr def);
-
#endif /* __VIR_XEN_COMMON_H__ */
--
2.10.1
8 years, 1 month
[libvirt] [Question] vhost-user hotplug: multiqueue hotplug seems doesn't pass mq and vectors
by Gaohaifeng (A)
Hi ALL:
Recently I review the vhost-user hotplug codes, when attach a vhost-user nic with multiqueue, it seems that it doesn't pass mq=on and vectors num to qemu.
Is there any special consideration or just a small mistake? Parts of codes:
qemuDomainAttachNetDevice(vhostfdSize is 0 when type is vhost-user)
qemuBuildNicDevStr:
if (usingVirtio && vhostfdSize > 1) {
if (net->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW) {
/* ccw provides a one to one relation of fds to queues and
* does not support the vectors option
*/
virBufferAddLit(&buf, ",mq=on");
} else {
/* As advised at http://www.linux-kvm.org/page/Multiqueue
* we should add vectors=2*N+2 where N is the vhostfdSize
*/
virBufferAsprintf(&buf, ",mq=on,vectors=%zu", 2 * vhostfdSize + 2);
}
}
Thanks.
Haifeng Gao
8 years, 1 month
[libvirt] [PATCH] qemu: Prevent detaching SCSI controller used by hostdev
by Eric Farman
Consider a guest started with the following XML snippet:
<controller type='scsi' model='virtio-scsi' index='0'/>
<hostdev mode='subsystem' type='scsi'>
<source>
<adapter name='scsi_host0'/>
<address bus='0' target='8' unit='1074151456'/>
</source>
</hostdev>
If we attach/create a virtio-scsi hostdev device but forget to include
a virtio-scsi controller, one is silently created for us. (See
qemuDomainFindOrCreateSCSIDiskController for context.)
Detaching the hostdev, followed by the controller, works well and the
guest behaves appropriately.
If we detach the virtio-scsi controller device first, Libvirt silently
detaches any associated hostdevs for us too. But all is not well,
as the guest is unable to receive new virtio-scsi devices (the attach
commands succeed, but devices never appear within the guest), nor even
be shutdown, after this point.
It appears that something is tied up in the host virtio layer.
While I investigate this, we can see if a controller is being used by
any hostdevs, and prevent the detach if it would lead us down this path.
$ virsh detach-device guest_one_virtio_scsi scsicontroller.xml
error: Failed to detach device from scsicontroller.xml
error: operation failed: device cannot be detached: device is busy
$ virsh detach-device guest_one_virtio_scsi scsidisk.xml
Device detached successfully
$ virsh detach-device guest_one_virtio_scsi scsicontroller.xml
Device detached successfully
Signed-off-by: Eric Farman <farman(a)linux.vnet.ibm.com>
Reviewed-by: Bjoern Walk <bwalk(a)linux.vnet.ibm.com>
Reviewed-by: Boris Fiuczynski <fiuczy(a)linux.vnet.ibm.com>
---
src/qemu/qemu_hotplug.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index b03e618..5db7abf 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -4443,6 +4443,7 @@ static bool qemuDomainDiskControllerIsBusy(virDomainObjPtr vm,
{
size_t i;
virDomainDiskDefPtr disk;
+ virDomainHostdevDefPtr hostdev;
for (i = 0; i < vm->def->ndisks; i++) {
disk = vm->def->disks[i];
@@ -4465,6 +4466,15 @@ static bool qemuDomainDiskControllerIsBusy(virDomainObjPtr vm,
return true;
}
+ for (i = 0; i < vm->def->nhostdevs; i++) {
+ hostdev = vm->def->hostdevs[i];
+ if (!virHostdevIsSCSIDevice(hostdev) ||
+ detach->type != VIR_DOMAIN_CONTROLLER_TYPE_SCSI)
+ continue;
+ if (hostdev->info->addr.drive.controller == detach->idx)
+ return true;
+ }
+
return false;
}
--
2.8.4
8 years, 1 month
[libvirt] [PATCH] loopback is not always just lo
by Pavel Timofeev
On BSD family OSes (Free/Net/Open/DragonFlyBSD, Mac OS) and
Solaris loopback interface is called 'lo0' instead of just 'lo'.
---
src/network/bridge_driver.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index a3ee3f3..9d94d65 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -1002,7 +1002,12 @@ networkDnsmasqConfContents(virNetworkObjPtr network,
virBufferAsprintf(&configbuf, "pid-file=%s\n", pidfile);
/* dnsmasq will *always* listen on localhost unless told otherwise */
+#ifdef __linux__
virBufferAddLit(&configbuf, "except-interface=lo\n");
+#else
+ /* BSD family OSes and Solaris call loopback interface as lo0 */
+ virBufferAddLit(&configbuf, "except-interface=lo0\n");
+#endif
if (dnsmasqCapsGet(caps, DNSMASQ_CAPS_BIND_DYNAMIC)) {
/* using --bind-dynamic with only --interface (no
--
2.9.2
8 years, 1 month