]> xenbits.xensource.com Git - people/liuw/libxenctrl-split/libvirt.git/commitdiff
qemu: hotplug: Fix mlock limit handling on memory hotplug
authorPeter Krempa <pkrempa@redhat.com>
Fri, 6 Nov 2015 15:39:31 +0000 (16:39 +0100)
committerPeter Krempa <pkrempa@redhat.com>
Tue, 10 Nov 2015 08:30:21 +0000 (09:30 +0100)
If mlock is required either due to use of VFIO hostdevs or due to the
fact that it's enabled it needs to be tweaked prior to adding new memory
or after removing a module. Add a helper to determine when it's
necessary and reuse it both on hotplug and hotunplug.

Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1273491

src/qemu/qemu_domain.c
src/qemu/qemu_domain.h
src/qemu/qemu_hotplug.c

index f016e8b3f6223256b21835458beb3063496a4eb3..416ab5b5dfebc5557bf1ebb55551ada7f09a508f 100644 (file)
@@ -3643,3 +3643,30 @@ qemuDomainGetMlockLimitBytes(virDomainDefPtr def)
 
     return memKB << 10;
 }
+
+
+/**
+ * @def: domain definition
+ *
+ * Returns ture if the locked memory limit needs to be set or updated due to
+ * configuration or passthrough devices.
+ * */
+bool
+qemuDomainRequiresMlock(virDomainDefPtr def)
+{
+    size_t i;
+
+    if (def->mem.locked)
+        return true;
+
+    for (i = 0; i < def->nhostdevs; i++) {
+        virDomainHostdevDefPtr dev = def->hostdevs[i];
+
+        if (dev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
+            dev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI &&
+            dev->source.subsys.u.pci.backend == VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO)
+            return true;
+    }
+
+    return false;
+}
index e34370b08b56eaebed915103ee22115f896e8af1..4be998c27d4ba392c3010a30c8969f2d8fb024f4 100644 (file)
@@ -483,5 +483,6 @@ int qemuDomainUpdateCurrentMemorySize(virQEMUDriverPtr driver,
                                       virDomainObjPtr vm);
 
 unsigned long long qemuDomainGetMlockLimitBytes(virDomainDefPtr def);
+bool qemuDomainRequiresMlock(virDomainDefPtr def);
 
 #endif /* __QEMU_DOMAIN_H__ */
index e7fc036471c21abe639fdf646f8c3b77a12c9dc9..b02e9050f2d9a2c25e02a759ecbc4f02b9e744e3 100644 (file)
@@ -1768,6 +1768,7 @@ qemuDomainAttachMemory(virQEMUDriverPtr driver,
     virJSONValuePtr props = NULL;
     virObjectEventPtr event;
     bool fix_balloon = false;
+    bool mlock = false;
     int id;
     int ret = -1;
 
@@ -1802,16 +1803,26 @@ qemuDomainAttachMemory(virQEMUDriverPtr driver,
         goto cleanup;
     }
 
+    mlock = qemuDomainRequiresMlock(vm->def);
+
+    if (mlock &&
+        virProcessSetMaxMemLock(vm->pid,
+                                qemuDomainGetMlockLimitBytes(vm->def)) < 0) {
+        mlock = false;
+        virJSONValueFree(props);
+        goto removedef;
+    }
+
     qemuDomainObjEnterMonitor(driver, vm);
     if (qemuMonitorAddObject(priv->mon, backendType, objalias, props) < 0)
-        goto removedef;
+        goto exit_monitor;
 
     if (qemuMonitorAddDevice(priv->mon, devstr) < 0) {
         virErrorPtr err = virSaveLastError();
         ignore_value(qemuMonitorDelObject(priv->mon, objalias));
         virSetError(err);
         virFreeError(err);
-        goto removedef;
+        goto exit_monitor;
     }
 
     if (qemuDomainObjExitMonitor(driver, vm) < 0) {
@@ -1845,17 +1856,27 @@ qemuDomainAttachMemory(virQEMUDriverPtr driver,
     virDomainMemoryDefFree(mem);
     return ret;
 
removedef:
exit_monitor:
     if (qemuDomainObjExitMonitor(driver, vm) < 0) {
         mem = NULL;
         goto audit;
     }
 
+ removedef:
     if ((id = virDomainMemoryFindByDef(vm->def, mem)) >= 0)
         mem = virDomainMemoryRemove(vm->def, id);
     else
         mem = NULL;
 
+    /* reset the mlock limit */
+    if (mlock) {
+        virErrorPtr err = virSaveLastError();
+        ignore_value(virProcessSetMaxMemLock(vm->pid,
+                                             qemuDomainGetMlockLimitBytes(vm->def)));
+        virSetError(err);
+        virFreeError(err);
+    }
+
     goto audit;
 }
 
@@ -2947,6 +2968,12 @@ qemuDomainRemoveMemoryDevice(virQEMUDriverPtr driver,
         virDomainMemoryRemove(vm->def, idx);
 
     virDomainMemoryDefFree(mem);
+
+    /* decrease the mlock limit after memory unplug if necessary */
+    if (qemuDomainRequiresMlock(vm->def))
+        ignore_value(virProcessSetMaxMemLock(vm->pid,
+                                             qemuDomainGetMlockLimitBytes(vm->def)));
+
     return 0;
 }