Signed-off-by: Luyao Huang <lhuang@xxxxxxxxxx> --- src/qemu/qemu_conf.h | 3 + src/qemu/qemu_driver.c | 4 ++ src/qemu/qemu_process.c | 157 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 164 insertions(+) diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h index ed9cd46..67a5c61 100644 --- a/src/qemu/qemu_conf.h +++ b/src/qemu/qemu_conf.h @@ -46,6 +46,7 @@ # include "virclosecallbacks.h" # include "virhostdev.h" # include "virfile.h" +# include "virshm.h" # ifdef CPU_SETSIZE /* Linux */ # define QEMUD_CPUMASK_LEN CPU_SETSIZE @@ -235,6 +236,8 @@ struct _virQEMUDriver { /* Immutable pointer. Unsafe APIs. XXX */ virHashTablePtr sharedDevices; + virShmObjectListPtr shmlist; + /* Immutable pointer, self-locking APIs */ virPortAllocatorPtr remotePorts; diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index b263ce0..f698ef8 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -776,6 +776,9 @@ qemuStateInitialize(bool privileged, if (qemuMigrationErrorInit(qemu_driver) < 0) goto error; + if (!(qemu_driver->shmlist = virShmObjectListGetDefault())) + goto error; + if (privileged) { char *channeldir; @@ -1085,6 +1088,7 @@ qemuStateCleanup(void) virObjectUnref(qemu_driver->config); virObjectUnref(qemu_driver->hostdevMgr); virHashFree(qemu_driver->sharedDevices); + virObjectUnref(qemu_driver->shmlist); virObjectUnref(qemu_driver->caps); virQEMUCapsCacheFree(qemu_driver->qemuCapsCache); diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index f7eb2b6..7b266e9 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -4323,6 +4323,153 @@ qemuPrepareNVRAM(virQEMUDriverConfigPtr cfg, } +static int +qemuPrepareShmemDevice(virQEMUDriverPtr driver, + virDomainObjPtr vm, + virDomainShmemDefPtr shmem) +{ + int ret = -1; + virShmObjectPtr tmp; + virShmObjectListPtr list = driver->shmlist; + bool othercreate = false; + char *path = NULL; + bool teardownshm = false; + int type, fd; + + virObjectLock(list); + + if ((tmp = virShmObjectFindByName(list, shmem->name))) { + if (shmem->size != virShmObjectGetSize(tmp)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Shmem object %s is already exists and " + "size is not equal require size"), + virShmObjectGetName(tmp)); + goto cleanup; + } + if (!shmem->shareable) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Cannot use a already exist shmem" + " device in a private way")); + goto cleanup; + } else if (!virShmObjectGetShareable(tmp)) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Cannot use a already exist private shmem" + " device in a shareable way")); + goto cleanup; + } + + if (virShmSetUsedDomain(tmp, QEMU_DRIVER_NAME, vm->def->name) < 0) + goto cleanup; + + if (virShmObjectSaveState(tmp, virShmObjectListGetStateFilePath(list)) < 0) + goto cleanup; + + virObjectUnlock(list); + return 0; + } + + if (!shmem->server.enabled) { + if ((fd = virShmCreate(shmem->name, shmem->size, + false, &othercreate, 0600)) < 0) + goto cleanup; + VIR_FORCE_CLOSE(fd); + + if (virShmBuildPath(shmem->name, &path) < 0) + goto cleanup; + + type = VIR_SHM_TYPE_SHM; + } else { + if (!virFileExists(shmem->server.chr.data.nix.path)) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Shmem device server socket is not exist")); + goto cleanup; + } else { + othercreate = true; + } + type = VIR_SHM_TYPE_SERVER; + } + teardownshm = true; + + if (!(tmp = virShmObjectNew(shmem->name, shmem->size, path, type, othercreate, + shmem->shareable, QEMU_DRIVER_NAME, vm->def->name))) + goto cleanup; + + if (virShmObjectSaveState(tmp, virShmObjectListGetStateFilePath(list)) < 0) { + virShmObjectFree(tmp); + goto cleanup; + } + + if (virShmObjectListAdd(list, tmp) < 0) { + virShmObjectFree(tmp); + goto cleanup; + } + + ret = 0; + + cleanup: + if (ret < 0) { + if (teardownshm && !shmem->server.enabled && + !othercreate && virShmUnlink(shmem->name) < 0) + VIR_WARN("Unable to unlink shared memory object"); + } + VIR_FREE(path); + virObjectUnlock(list); + return ret; +} + + +static int +qemuCleanUpShmemDevice(virQEMUDriverPtr driver, + virDomainObjPtr vm, + virDomainShmemDefPtr shmem) +{ + virShmObjectPtr tmp; + virShmObjectListPtr list = driver->shmlist; + int ret = -1; + + virObjectLock(list); + + if (!(tmp = virShmObjectFindByName(list, shmem->name))) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Cannot find share memory named '%s'"), + shmem->name); + goto cleanup; + } + if ((shmem->server.enabled && + virShmObjectGetType(tmp) != VIR_SHM_TYPE_SERVER) || + (!shmem->server.enabled && + virShmObjectGetType(tmp) != VIR_SHM_TYPE_SHM)) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Shmem object and shmem device type is not equal")); + goto cleanup; + } + + if (virShmRemoveUsedDomain(tmp, QEMU_DRIVER_NAME, vm->def->name) < 0) + goto cleanup; + + if (virShmObjectSaveState(tmp, virShmObjectListGetStateFilePath(list)) < 0) + goto cleanup; + + if (virShmObjectGetUsedDomainNumber(tmp) == 0) { + if (!shmem->server.enabled) { + if (!virShmObjectGetOtherCreate(tmp) && + virShmUnlink(virShmObjectGetName(tmp)) < 0) + VIR_WARN("Unable to unlink shared memory object"); + } + + if (virShmObjectRemoveStateFile(list, virShmObjectGetName(tmp)) < 0) + goto cleanup; + virShmObjectListDel(list, tmp); + virShmObjectFree(tmp); + } + + ret = 0; + cleanup: + virObjectUnlock(list); + return ret; +} + + static void qemuLogOperation(virDomainObjPtr vm, const char *msg, @@ -4786,6 +4933,11 @@ int qemuProcessStart(virConnectPtr conn, if (cfg->clearEmulatorCapabilities) virCommandClearCaps(cmd); + for (i = 0; i < vm->def->nshmems; i++) { + if (qemuPrepareShmemDevice(driver, vm, vm->def->shmems[i]) < 0) + goto cleanup; + } + /* in case a certain disk is desirous of CAP_SYS_RAWIO, add this */ for (i = 0; i < vm->def->ndisks; i++) { virDomainDeviceDef dev; @@ -5438,6 +5590,11 @@ void qemuProcessStop(virQEMUDriverPtr driver, } } + for (i = 0; i < vm->def->nshmems; i++) { + ignore_value(qemuCleanUpShmemDevice(driver, vm, + vm->def->shmems[i])); + } + vm->taint = 0; vm->pid = -1; virDomainObjSetState(vm, VIR_DOMAIN_SHUTOFF, reason); -- 1.8.3.1 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list