]> xenbits.xensource.com Git - xen.git/commitdiff
libxl: convert libxl_device_nic_add to an async operation
authorRoger Pau Monne <roger.pau@citrix.com>
Thu, 26 Jul 2012 15:47:31 +0000 (16:47 +0100)
committerRoger Pau Monne <roger.pau@citrix.com>
Thu, 26 Jul 2012 15:47:31 +0000 (16:47 +0100)
This patch converts libxl_device_nic_add to an ao operation that
waits for device backend to reach state XenbusStateInitWait and then
marks the operation as completed. This is not really useful now, but
will be used by latter patches that will launch hotplug scripts after
we reached the desired xenbus state.

Calls to libxl_device_nic_add have also been moved to occur after the
device model has been launched, so when hotplug scripts are called
from this functions the interfaces already exists.

As usual, libxl_device_nic_add callers have been modified, and the
internal function libxl__device_disk_add has been used if the call was
inside an already running ao.

Signed-off-by: Roger Pau Monne <roger.pau@citrix.com>
Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>
Committed-by: Ian Campbell <ian.campbell@citrix.com>
tools/libxl/libxl.c
tools/libxl/libxl.h
tools/libxl/libxl_create.c
tools/libxl/libxl_device.c
tools/libxl/libxl_dm.c
tools/libxl/libxl_internal.h
tools/libxl/xl_cmdimpl.c
tools/ocaml/libs/xl/xenlight_stubs.c

index 85475586bad5e20e63569c71389197e3f2fab450..0a5e4e9ee24da0bef06a6feda95a084a1d67c254 100644 (file)
@@ -2506,12 +2506,13 @@ static int libxl__device_from_nic(libxl__gc *gc, uint32_t domid,
     return 0;
 }
 
-int libxl_device_nic_add(libxl_ctx *ctx, uint32_t domid, libxl_device_nic *nic)
+void libxl__device_nic_add(libxl__egc *egc, uint32_t domid,
+                           libxl_device_nic *nic, libxl__ao_device *aodev)
 {
-    GC_INIT(ctx);
+    STATE_AO_GC(aodev->ao);
     flexarray_t *front;
     flexarray_t *back;
-    libxl__device device;
+    libxl__device *device;
     char *dompath, **l;
     unsigned int nb, rc;
 
@@ -2542,7 +2543,8 @@ int libxl_device_nic_add(libxl_ctx *ctx, uint32_t domid, libxl_device_nic *nic)
         }
     }
 
-    rc = libxl__device_from_nic(gc, domid, nic, &device);
+    GCNEW(device);
+    rc = libxl__device_from_nic(gc, domid, nic, device);
     if ( rc != 0 ) goto out_free;
 
     flexarray_append(back, "frontend-id");
@@ -2583,6 +2585,9 @@ int libxl_device_nic_add(libxl_ctx *ctx, uint32_t domid, libxl_device_nic *nic)
     flexarray_append(back, libxl__strdup(gc, nic->bridge));
     flexarray_append(back, "handle");
     flexarray_append(back, libxl__sprintf(gc, "%d", nic->devid));
+    flexarray_append(back, "type");
+    flexarray_append(back, libxl__strdup(gc,
+                                     libxl_nic_type_to_string(nic->nictype)));
 
     flexarray_append(front, "backend-id");
     flexarray_append(front, libxl__sprintf(gc, "%d", nic->backend_domid));
@@ -2593,18 +2598,22 @@ int libxl_device_nic_add(libxl_ctx *ctx, uint32_t domid, libxl_device_nic *nic)
     flexarray_append(front, "mac");
     flexarray_append(front, libxl__sprintf(gc,
                                     LIBXL_MAC_FMT, LIBXL_MAC_BYTES(nic->mac)));
-    libxl__device_generic_add(gc, XBT_NULL, &device,
+    libxl__device_generic_add(gc, XBT_NULL, device,
                              libxl__xs_kvs_of_flexarray(gc, back, back->count),
                              libxl__xs_kvs_of_flexarray(gc, front, front->count));
 
-    /* FIXME: wait for plug */
+    aodev->dev = device;
+    aodev->action = DEVICE_CONNECT;
+    libxl__wait_device_connection(egc, aodev);
+
     rc = 0;
 out_free:
     flexarray_free(back);
     flexarray_free(front);
 out:
-    GC_FREE;
-    return rc;
+    aodev->rc = rc;
+    if (rc) aodev->callback(egc, aodev);
+    return;
 }
 
 static void libxl__device_nic_from_xs_be(libxl__gc *gc,
@@ -3096,6 +3105,7 @@ DEFINE_DEVICE_REMOVE(vfb, destroy, 1)
 /* Macro for defining device addition functions in a compact way */
 /* The following functions are defined:
  * libxl_device_disk_add
+ * libxl_device_nic_add
  */
 
 #define DEFINE_DEVICE_ADD(type)                                         \
@@ -3119,6 +3129,9 @@ DEFINE_DEVICE_REMOVE(vfb, destroy, 1)
 /* disk */
 DEFINE_DEVICE_ADD(disk)
 
+/* nic */
+DEFINE_DEVICE_ADD(nic)
+
 #undef DEFINE_DEVICE_ADD
 
 /******************************************************************************/
index cc872ba97101f0ca7199cf788899e4f00c599fd6..e6e549f318165fed95d894d37563227756539d27 100644 (file)
@@ -697,7 +697,8 @@ int libxl_cdrom_insert(libxl_ctx *ctx, uint32_t domid, libxl_device_disk *disk,
                        const libxl_asyncop_how *ao_how);
 
 /* Network Interfaces */
-int libxl_device_nic_add(libxl_ctx *ctx, uint32_t domid, libxl_device_nic *nic);
+int libxl_device_nic_add(libxl_ctx *ctx, uint32_t domid, libxl_device_nic *nic,
+                         const libxl_asyncop_how *ao_how);
 int libxl_device_nic_remove(libxl_ctx *ctx, uint32_t domid,
                             libxl_device_nic *nic,
                             const libxl_asyncop_how *ao_how);
index 0d47eb472aed0d7e9cedb3ddde45f4121854845a..707e7dd7283a09df56bdfe85d3f33647f5780d70 100644 (file)
@@ -564,6 +564,9 @@ static void domcreate_bootloader_done(libxl__egc *egc,
 static void domcreate_launch_dm(libxl__egc *egc, libxl__ao_devices *aodevs,
                                 int ret);
 
+static void domcreate_attach_pci(libxl__egc *egc, libxl__ao_devices *aodevs,
+                                 int ret);
+
 static void domcreate_console_available(libxl__egc *egc,
                                         libxl__domain_create_state *dcs);
 
@@ -898,13 +901,11 @@ static void domcreate_launch_dm(libxl__egc *egc, libxl__ao_devices *aodevs,
         goto error_out;
     }
     for (i = 0; i < d_config->num_nics; i++) {
-        ret = libxl_device_nic_add(ctx, domid, &d_config->nics[i]);
-        if (ret) {
-            LIBXL__LOG(ctx, LIBXL__LOG_ERROR,
-                       "cannot add nic %d to domain: %d", i, ret);
-            ret = ERROR_FAIL;
-            goto error_out;
-        }
+        /* We have to init the nic here, because we still haven't
+         * called libxl_device_nic_add at this point, but qemu needs
+         * the nic information to be complete.
+         */
+        libxl__device_nic_setdefault(gc, &d_config->nics[i]);
     }
     switch (d_config->c_info.type) {
     case LIBXL_DOMAIN_TYPE_HVM:
@@ -977,7 +978,6 @@ static void domcreate_devmodel_started(libxl__egc *egc,
 {
     libxl__domain_create_state *dcs = CONTAINER_OF(dmss, *dcs, dmss.dm);
     STATE_AO_GC(dmss->spawn.ao);
-    int i;
     libxl_ctx *ctx = CTX;
     int domid = dcs->guest_domid;
 
@@ -997,6 +997,41 @@ static void domcreate_devmodel_started(libxl__egc *egc,
         }
     }
 
+    /* Plug nic interfaces */
+    if (d_config->num_nics > 0) {
+        /* Attach nics */
+        dcs->aodevs.size = d_config->num_nics;
+        dcs->aodevs.callback = domcreate_attach_pci;
+        libxl__prepare_ao_devices(ao, &dcs->aodevs);
+        libxl__add_nics(egc, ao, domid, 0, d_config, &dcs->aodevs);
+        return;
+    }
+
+    domcreate_attach_pci(egc, &dcs->aodevs, 0);
+    return;
+
+error_out:
+    assert(ret);
+    domcreate_complete(egc, dcs, ret);
+}
+
+static void domcreate_attach_pci(libxl__egc *egc, libxl__ao_devices *aodevs,
+                                 int ret)
+{
+    libxl__domain_create_state *dcs = CONTAINER_OF(aodevs, *dcs, aodevs);
+    STATE_AO_GC(dcs->ao);
+    int i;
+    libxl_ctx *ctx = CTX;
+    int domid = dcs->guest_domid;
+
+    /* convenience aliases */
+    libxl_domain_config *const d_config = dcs->guest_config;
+
+    if (ret) {
+        LOG(ERROR, "unable to add nic devices");
+        goto error_out;
+    }
+
     for (i = 0; i < d_config->num_pcidevs; i++)
         libxl__device_pci_add(gc, domid, &d_config->pcidevs[i], 1);
 
index 835b4ad23546079a510c3d8eb272a415bf46b4ab..ed33f6f644051e30cf1291ef09a0544f9e30eeb7 100644 (file)
@@ -455,6 +455,7 @@ void libxl__ao_devices_callback(libxl__egc *egc, libxl__ao_device *aodev)
  *
  * The following functions are defined:
  * libxl__add_disks
+ * libxl__add_nics
  */
 
 #define DEFINE_DEVICES_ADD(type)                                               \
@@ -473,6 +474,7 @@ void libxl__ao_devices_callback(libxl__egc *egc, libxl__ao_device *aodev)
     }
 
 DEFINE_DEVICES_ADD(disk)
+DEFINE_DEVICES_ADD(nic)
 
 #undef DEFINE_DEVICES_ADD
 
index 8a731ae500b14b6eb8a336b4baf452d785086db8..1b17ef516fc04aa545197e1ea8718a2946fd8896 100644 (file)
@@ -716,6 +716,10 @@ static void spawn_stubdom_pvqemu_cb(libxl__egc *egc,
 static void spawn_stub_launch_dm(libxl__egc *egc,
                                  libxl__ao_devices *aodevs, int ret);
 
+static void stubdom_pvqemu_cb(libxl__egc *egc,
+                              libxl__ao_devices *aodevs,
+                              int rc);
+
 static void spaw_stubdom_pvqemu_destroy_cb(libxl__egc *egc,
                                            libxl__destroy_domid_state *dis,
                                            int rc);
@@ -887,9 +891,11 @@ static void spawn_stub_launch_dm(libxl__egc *egc,
      }
 
     for (i = 0; i < dm_config->num_nics; i++) {
-        ret = libxl_device_nic_add(ctx, dm_domid, &dm_config->nics[i]);
-        if (ret)
-            goto out;
+         /* We have to init the nic here, because we still haven't
+         * called libxl_device_nic_add at this point, but qemu needs
+         * the nic information to be complete.
+         */
+        libxl__device_nic_setdefault(gc, &dm_config->nics[i]);
     }
     ret = libxl_device_vfb_add(ctx, dm_domid, &dm_config->vfbs[0]);
     if (ret)
@@ -966,9 +972,35 @@ static void spawn_stubdom_pvqemu_cb(libxl__egc *egc,
         CONTAINER_OF(stubdom_dmss, *sdss, pvqemu);
     STATE_AO_GC(sdss->dm.spawn.ao);
     uint32_t dm_domid = sdss->pvqemu.guest_domid;
+    libxl_domain_config *d_config = stubdom_dmss->guest_config;
 
     if (rc) goto out;
 
+    if (d_config->num_nics > 0) {
+        sdss->aodevs.size = d_config->num_nics;
+        sdss->aodevs.callback = stubdom_pvqemu_cb;
+        libxl__prepare_ao_devices(ao, &sdss->aodevs);
+        libxl__add_nics(egc, ao, dm_domid, 0, d_config, &sdss->aodevs);
+        return;
+    }
+
+out:
+    stubdom_pvqemu_cb(egc, &sdss->aodevs, rc);
+}
+
+static void stubdom_pvqemu_cb(libxl__egc *egc,
+                              libxl__ao_devices *aodevs,
+                              int rc)
+{
+    libxl__stub_dm_spawn_state *sdss = CONTAINER_OF(aodevs, *sdss, aodevs);
+    STATE_AO_GC(sdss->dm.spawn.ao);
+    uint32_t dm_domid = sdss->pvqemu.guest_domid;
+
+    if (rc) {
+        LOGE(ERROR, "error connecting nics devices");
+        goto out;
+    }
+
     rc = libxl_domain_unpause(CTX, dm_domid);
     if (rc) goto out;
 
index 19a9cdc39c4f498669b1a944129d21f92ac0e3b0..e89f37c29676691f2201618fa6949a46d0a57efc 100644 (file)
@@ -1933,6 +1933,11 @@ _hidden void libxl__device_disk_add(libxl__egc *egc, uint32_t domid,
                                     libxl_device_disk *disk,
                                     libxl__ao_device *aodev);
 
+/* AO operation to connect a nic device */
+_hidden void libxl__device_nic_add(libxl__egc *egc, uint32_t domid,
+                                   libxl_device_nic *nic,
+                                   libxl__ao_device *aodev);
+
 /* Waits for the passed device to reach state XenbusStateInitWait.
  * This is not really useful by itself, but is important when executing
  * hotplug scripts, since we need to be sure the device is in the correct
@@ -2328,6 +2333,10 @@ _hidden void libxl__add_disks(libxl__egc *egc, libxl__ao *ao, uint32_t domid,
                               int start, libxl_domain_config *d_config,
                               libxl__ao_devices *aodevs);
 
+_hidden void libxl__add_nics(libxl__egc *egc, libxl__ao *ao, uint32_t domid,
+                             int start, libxl_domain_config *d_config,
+                             libxl__ao_devices *aodevs);
+
 /*----- device model creation -----*/
 
 /* First layer; wraps libxl__spawn_spawn. */
index 8fbd4483b4344b66b8ed3132706487066c6366e2..72892f3dfdccf20c7ba51339486a0a6b8eb9439a 100644 (file)
@@ -5249,7 +5249,7 @@ int main_networkattach(int argc, char **argv)
         return 0;
     }
 
-    if (libxl_device_nic_add(ctx, domid, &nic)) {
+    if (libxl_device_nic_add(ctx, domid, &nic, 0)) {
         fprintf(stderr, "libxl_device_nic_add failed.\n");
         return 1;
     }
index a1583517940dc5aa4396f4fcd41e71b31cb53ba5..0e9c65e8cd580bc331bda201ba43efaa724d4e5c 100644 (file)
@@ -281,7 +281,7 @@ value stub_xl_device_nic_add(value info, value domid)
        device_nic_val(&gc, &lg, &c_info, info);
 
        INIT_CTX();
-       ret = libxl_device_nic_add(ctx, Int_val(domid), &c_info);
+       ret = libxl_device_nic_add(ctx, Int_val(domid), &c_info, 0);
        if (ret != 0)
                failwith_xl("nic_add", &lg);
        FREE_CTX();