[libvirt] [PATCH 4/4] qemu: call the helpers in virshm.c to manage shmem device

Luyao Huang lhuang at redhat.com
Thu Jul 23 10:13:49 UTC 2015


Signed-off-by: Luyao Huang <lhuang at redhat.com>
---
 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




More information about the libvir-list mailing list