Signed-off-by: Luyao Huang <lhuang@xxxxxxxxxx> --- src/qemu/qemu_conf.h | 3 + src/qemu/qemu_driver.c | 4 ++ src/qemu/qemu_process.c | 158 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 165 insertions(+) diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h index 3f73929..61d3462 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 9dbe635..282ab45 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -778,6 +778,9 @@ qemuStateInitialize(bool privileged, if (qemuMigrationErrorInit(qemu_driver) < 0) goto error; + if (!(qemu_driver->shmlist = virShmObjectListGetDefault())) + goto error; + if (privileged) { char *channeldir; @@ -1087,6 +1090,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 1c0c734..84b3b5e 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -4321,6 +4321,154 @@ 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 teardownlabel = false; + bool teardownshm = false; + int type, fd; + + virObjectLock(list); + + if ((tmp = virShmObjectFindByName(list, shmem->name))) { + if (shmem->size > tmp->size) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Shmem object %s is already exists and " + "size is smaller than require size"), + tmp->name); + goto cleanup; + } + + if (virShmSetUsedDomain(tmp, QEMU_DRIVER_NAME, vm->def->name) < 0) + goto cleanup; + + if (virShmObjectSaveState(tmp, list->stateDir) < 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 ((ret = virShmBuildPath(shmem->name, &path)) == -1) { + ignore_value(virShmUnlink(shmem->name)); + goto cleanup; + } else if (ret == -2 && !othercreate) { + ignore_value(virShmUnlink(shmem->name)); + } + 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 (virSecurityManagerSetShmemLabel(driver->securityManager, + vm->def, shmem, path) < 0) + goto cleanup; + teardownlabel = true; + + if (!(tmp = virShmObjectNew(shmem->name, shmem->size, path, type, othercreate, + QEMU_DRIVER_NAME, vm->def->name))) + goto cleanup; + + if (virShmObjectSaveState(tmp, list->stateDir) < 0) { + virShmObjectFree(tmp); + goto cleanup; + } + + if (virShmObjectListAdd(list, tmp) < 0) { + virShmObjectFree(tmp); + goto cleanup; + } + + ret = 0; + + cleanup: + if (ret < 0) { + if (teardownlabel && + virSecurityManagerRestoreShmemLabel(driver->securityManager, + vm->def, shmem, path) < 0) + VIR_WARN("Unable to restore shared memory device labelling"); + + 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 && tmp->type != VIR_SHM_TYPE_SERVER) || + (!shmem->server.enabled && tmp->type != 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 (tmp->ndomains == 0) { + if (virSecurityManagerRestoreShmemLabel(driver->securityManager, + vm->def, shmem, tmp->path) < 0) + VIR_WARN("Unable to restore shared memory device labelling"); + + if (!shmem->server.enabled) { + if (!tmp->othercreate && + virShmUnlink(tmp->name) < 0) + VIR_WARN("Unable to unlink shared memory object"); + } + + if (virShmObjectRemoveStateFile(list, tmp->name) < 0) + goto cleanup; + virShmObjectListDel(list, tmp); + virShmObjectFree(tmp); + } + + ret = 0; + cleanup: + virObjectUnlock(list); + return ret; +} + + static void qemuLogOperation(virDomainObjPtr vm, const char *msg, @@ -4753,6 +4901,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; @@ -5391,6 +5544,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