]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
qemu: Allow to attach/detach controller device persistently
authorOsier Yang <jyang@redhat.com>
Mon, 23 Jul 2012 08:18:57 +0000 (16:18 +0800)
committerOsier Yang <jyang@redhat.com>
Fri, 3 Aug 2012 04:19:16 +0000 (12:19 +0800)
* src/conf/domain_conf.c:
  - Add virDomainControllerFind to find controller device by type
    and index.
  - Add virDomainControllerRemove to remove the controller device
    from maintained controler list.

* src/conf/domain_conf.h:
  - Declare the two new helpers.

* src/libvirt_private.syms:
  - Expose private symbols for the two new helpers.

* src/qemu/qemu_driver.c:
  - Support attach/detach controller device persistently

* src/qemu/qemu_hotplug.c:
  - Use the two helpers to simplify the codes.

src/conf/domain_conf.c
src/conf/domain_conf.h
src/libvirt_private.syms
src/qemu/qemu_driver.c
src/qemu/qemu_hotplug.c

index 43b3f804afdf88918398c8c9112bd2a76e776a4c..58603a37104d10ae81a16bea92d0135be393f876 100644 (file)
@@ -7556,6 +7556,43 @@ void virDomainControllerInsertPreAlloced(virDomainDefPtr def,
     def->ncontrollers++;
 }
 
+int
+virDomainControllerFind(virDomainDefPtr def,
+                        int type, int idx)
+{
+    int i;
+
+    for (i = 0 ; i < def->ncontrollers ; i++) {
+        if ((def->controllers[i]->type == type) &&
+            (def->controllers[i]->idx == idx)) {
+            return i;
+        }
+    }
+
+    return -1;
+}
+
+virDomainControllerDefPtr
+virDomainControllerRemove(virDomainDefPtr def, size_t i)
+{
+    virDomainControllerDefPtr controller = def->controllers[i];
+
+    if (def->ncontrollers > 1) {
+        memmove(def->controllers + i,
+                def->controllers + i + 1,
+                sizeof(*def->controllers) *
+                (def->ncontrollers - (i + 1)));
+        def->ncontrollers--;
+        if (VIR_REALLOC_N(def->controllers, def->ncontrollers) < 0) {
+            /* ignore, harmless */
+        }
+    } else {
+        VIR_FREE(def->controllers);
+        def->ncontrollers = 0;
+    }
+
+    return controller;
+}
 
 int virDomainLeaseIndex(virDomainDefPtr def,
                         virDomainLeaseDefPtr lease)
index 9fdda785ce3be5eebc66fcdf461247fc9e45ae31..f4c43c64c907ec08f9fe31d5f0d88152c699fcfe 100644 (file)
@@ -2048,7 +2048,8 @@ int virDomainControllerInsert(virDomainDefPtr def,
                               virDomainControllerDefPtr controller);
 void virDomainControllerInsertPreAlloced(virDomainDefPtr def,
                                          virDomainControllerDefPtr controller);
-
+int virDomainControllerFind(virDomainDefPtr def, int type, int idx);
+virDomainControllerDefPtr virDomainControllerRemove(virDomainDefPtr def, size_t i);
 
 int virDomainLeaseIndex(virDomainDefPtr def,
                         virDomainLeaseDefPtr lease);
index aace7486a1da77daefde8f61b7189949ef14dedb..75997fedea014ff3283b9fdfd8094cbdf8bb80dc 100644 (file)
@@ -266,12 +266,14 @@ virDomainClockOffsetTypeFromString;
 virDomainClockOffsetTypeToString;
 virDomainConfigFile;
 virDomainControllerDefFree;
+virDomainControllerFind;
 virDomainControllerInsert;
 virDomainControllerInsertPreAlloced;
 virDomainControllerModelSCSITypeFromString;
 virDomainControllerModelSCSITypeToString;
 virDomainControllerModelUSBTypeFromString;
 virDomainControllerModelUSBTypeToString;
+virDomainControllerRemove;
 virDomainControllerTypeToString;
 virDomainCpuPlacementModeTypeFromString;
 virDomainCpuPlacementModeTypeToString;
index 270e4dd93aae8bb9196b6f54cce48d2af95abb40..369e8edd9eeff684d0bfad57cf862041b93d6c2a 100644 (file)
@@ -5535,6 +5535,7 @@ qemuDomainAttachDeviceConfig(virDomainDefPtr vmdef,
     virDomainNetDefPtr net;
     virDomainHostdevDefPtr hostdev;
     virDomainLeaseDefPtr lease;
+    virDomainControllerDefPtr controller;
 
     switch (dev->type) {
     case VIR_DOMAIN_DEVICE_DISK:
@@ -5607,6 +5608,23 @@ qemuDomainAttachDeviceConfig(virDomainDefPtr vmdef,
         dev->data.lease = NULL;
         break;
 
+    case VIR_DOMAIN_DEVICE_CONTROLLER:
+        controller = dev->data.controller;
+        if (virDomainControllerFind(vmdef, controller->type,
+                                    controller->idx) > 0) {
+            virReportError(VIR_ERR_INVALID_ARG, "%s",
+                           _("Target already exists"));
+            return -1;
+        }
+
+        if (virDomainControllerInsert(vmdef, controller) < 0)
+            return -1;
+        dev->data.controller = NULL;
+
+        if (qemuDomainAssignAddresses(vmdef, NULL, NULL) < 0)
+            return -1;
+        break;
+
     default:
          virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                         _("persistent attach of device is not supported"));
@@ -5624,6 +5642,8 @@ qemuDomainDetachDeviceConfig(virDomainDefPtr vmdef,
     virDomainNetDefPtr net, det_net;
     virDomainHostdevDefPtr hostdev, det_hostdev;
     virDomainLeaseDefPtr lease, det_lease;
+    virDomainControllerDefPtr cont, det_cont;
+    int idx;
 
     switch (dev->type) {
     case VIR_DOMAIN_DEVICE_DISK:
@@ -5650,8 +5670,6 @@ qemuDomainDetachDeviceConfig(virDomainDefPtr vmdef,
         break;
 
     case VIR_DOMAIN_DEVICE_HOSTDEV: {
-        int idx;
-
         hostdev = dev->data.hostdev;
         if ((idx = virDomainHostdevFind(vmdef, hostdev, &det_hostdev)) < 0) {
             virReportError(VIR_ERR_INVALID_ARG, "%s",
@@ -5674,6 +5692,19 @@ qemuDomainDetachDeviceConfig(virDomainDefPtr vmdef,
         virDomainLeaseDefFree(det_lease);
         break;
 
+    case VIR_DOMAIN_DEVICE_CONTROLLER:
+        cont = dev->data.controller;
+        if ((idx = virDomainControllerFind(vmdef, cont->type,
+                                           cont->idx)) < 0) {
+            virReportError(VIR_ERR_INVALID_ARG, "%s",
+                           _("device not present in domain configuration"));
+            return -1;
+        }
+        det_cont = virDomainControllerRemove(vmdef, idx);
+        virDomainControllerDefFree(det_cont);
+
+        break;
+
     default:
         virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                        _("persistent detach of device is not supported"));
index f5f96ed8ddd644c9f8a94005aabb52e826e2ee38..71ec48438b914f1efdb3f18e551c8b06d2f85bc8 100644 (file)
@@ -308,21 +308,17 @@ int qemuDomainAttachPciControllerDevice(struct qemud_driver *driver,
                                         virDomainObjPtr vm,
                                         virDomainControllerDefPtr controller)
 {
-    int i;
     int ret = -1;
     const char* type = virDomainControllerTypeToString(controller->type);
     char *devstr = NULL;
     qemuDomainObjPrivatePtr priv = vm->privateData;
     bool releaseaddr = false;
 
-    for (i = 0 ; i < vm->def->ncontrollers ; i++) {
-        if ((vm->def->controllers[i]->type == controller->type) &&
-            (vm->def->controllers[i]->idx == controller->idx)) {
-            virReportError(VIR_ERR_OPERATION_FAILED,
-                           _("target %s:%d already exists"),
-                           type, controller->idx);
-            return -1;
-        }
+    if (virDomainControllerFind(vm->def, controller->type, controller->idx) > 0) {
+        virReportError(VIR_ERR_OPERATION_FAILED,
+                       _("target %s:%d already exists"),
+                       type, controller->idx);
+        return -1;
     }
 
     if (qemuCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE)) {
@@ -1875,19 +1871,13 @@ int qemuDomainDetachPciControllerDevice(struct qemud_driver *driver,
                                         virDomainObjPtr vm,
                                         virDomainDeviceDefPtr dev)
 {
-    int i, ret = -1;
+    int idx, ret = -1;
     virDomainControllerDefPtr detach = NULL;
     qemuDomainObjPrivatePtr priv = vm->privateData;
 
-    for (i = 0 ; i < vm->def->ncontrollers ; i++) {
-        if ((vm->def->controllers[i]->type == dev->data.controller->type) &&
-            (vm->def->controllers[i]->idx == dev->data.controller->idx)) {
-            detach = vm->def->controllers[i];
-            break;
-        }
-    }
-
-    if (!detach) {
+    if ((idx = virDomainControllerFind(vm->def,
+                                       dev->data.controller->type,
+                                       dev->data.controller->idx)) < 0) {
         virReportError(VIR_ERR_OPERATION_FAILED,
                        _("disk controller %s:%d not found"),
                        virDomainControllerTypeToString(dev->data.controller->type),
@@ -1895,6 +1885,8 @@ int qemuDomainDetachPciControllerDevice(struct qemud_driver *driver,
         goto cleanup;
     }
 
+    detach = vm->def->controllers[idx];
+
     if (!virDomainDeviceAddressIsValid(&detach->info,
                                        VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI)) {
         virReportError(VIR_ERR_OPERATION_FAILED, "%s",
@@ -1935,27 +1927,14 @@ int qemuDomainDetachPciControllerDevice(struct qemud_driver *driver,
     }
     qemuDomainObjExitMonitorWithDriver(driver, vm);
 
-    if (vm->def->ncontrollers > 1) {
-        memmove(vm->def->controllers + i,
-                vm->def->controllers + i + 1,
-                sizeof(*vm->def->controllers) *
-                (vm->def->ncontrollers - (i + 1)));
-        vm->def->ncontrollers--;
-        if (VIR_REALLOC_N(vm->def->controllers, vm->def->ncontrollers) < 0) {
-            /* ignore, harmless */
-        }
-    } else {
-        VIR_FREE(vm->def->controllers);
-        vm->def->ncontrollers = 0;
-    }
+    virDomainControllerRemove(vm->def, idx);
+    virDomainControllerDefFree(detach);
 
     if (qemuCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE) &&
         qemuDomainPCIAddressReleaseSlot(priv->pciaddrs,
                                         detach->info.addr.pci.slot) < 0)
         VIR_WARN("Unable to release PCI address on controller");
 
-    virDomainControllerDefFree(detach);
-
     ret = 0;
 
 cleanup: