[PATCHv2 5/5] qemu: call the helpers in virshm.c to manage shmem device

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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



[Index of Archives]     [Virt Tools]     [Libvirt Users]     [Lib OS Info]     [Fedora Users]     [Fedora Desktop]     [Fedora SELinux]     [Big List of Linux Books]     [Yosemite News]     [KDE Users]     [Fedora Tools]