return 0;
}
+static LIBXL_DEFINE_UPDATE_DEVID(p9, "9pfs")
int libxl__device_p9_add(libxl__gc *gc, uint32_t domid,
libxl_device_p9 *p9)
front = flexarray_make(gc, 16, 1);
back = flexarray_make(gc, 16, 1);
- if (p9->devid == -1) {
- if ((p9->devid = libxl__device_nextid(gc, domid, "9pfs")) < 0) {
- rc = ERROR_FAIL;
- goto out;
- }
- }
+ rc = libxl__device_p9_update_devid(gc, domid, p9);
+ if (rc) goto out;
rc = libxl__device_from_p9(gc, domid, p9, &device);
if (rc != 0) goto out;
return AO_INPROGRESS;
}
+static LIBXL_DEFINE_UPDATE_DEVID(vkb, "vkb")
+
int libxl__device_vkb_add(libxl__gc *gc, uint32_t domid,
libxl_device_vkb *vkb)
{
front = flexarray_make(gc, 16, 1);
back = flexarray_make(gc, 16, 1);
- if (vkb->devid == -1) {
- if ((vkb->devid = libxl__device_nextid(gc, domid, "vkb")) < 0) {
- rc = ERROR_FAIL;
- goto out;
- }
- }
+ rc = libxl__device_vkb_update_devid(gc, domid, vkb);
+ if (rc) goto out;
rc = libxl__device_from_vkb(gc, domid, vkb, &device);
if (rc != 0) goto out;
return AO_INPROGRESS;
}
+static LIBXL_DEFINE_UPDATE_DEVID(vfb, "vfb")
+
int libxl__device_vfb_add(libxl__gc *gc, uint32_t domid, libxl_device_vfb *vfb)
{
flexarray_t *front;
front = flexarray_make(gc, 16, 1);
back = flexarray_make(gc, 16, 1);
- if (vfb->devid == -1) {
- if ((vfb->devid = libxl__device_nextid(gc, domid, "vfb")) < 0) {
- rc = ERROR_FAIL;
- goto out;
- }
- }
+ rc = libxl__device_vfb_update_devid(gc, domid, vfb);
+ if (rc) goto out;
rc = libxl__device_from_vfb(gc, domid, vfb, &device);
if (rc != 0) goto out;
store_libxl_entry(gc, domid, &d_config->b_info);
for (i = 0; i < d_config->num_disks; i++) {
- ret = libxl__device_disk_setdefault(gc, &d_config->disks[i], domid);
+ ret = libxl__device_disk_setdefault(gc, domid, &d_config->disks[i],
+ false);
if (ret) {
LOGD(ERROR, domid, "Unable to set disk defaults for disk %d", i);
goto error_out;
#define libxl_device_dtdev_list NULL
#define libxl_device_dtdev_compare NULL
+#define libxl__device_from_dtdev NULL
+#define libxl__device_dtdev_setdefault NULL
+#define libxl__device_dtdev_update_devid NULL
static DEFINE_DEVICE_TYPE_STRUCT(dtdev);
const struct libxl_device_type *device_type_tbl[] = {
return AO_CREATE_FAIL(rc);
}
+static void device_add_domain_config(libxl__gc *gc,
+ libxl_domain_config *d_config,
+ const struct libxl_device_type *dt,
+ void *type)
+{
+ int *num_dev;
+ unsigned int i;
+ void *item = NULL;
+
+ num_dev = libxl__device_type_get_num(dt, d_config);
+
+ /* Check for existing device */
+ for (i = 0; i < *num_dev; i++) {
+ if (dt->compare(libxl__device_type_get_elem(dt, d_config, i), type)) {
+ item = libxl__device_type_get_elem(dt, d_config, i);
+ }
+ }
+
+ if (!item) {
+ void **devs = libxl__device_type_get_ptr(dt, d_config);
+ *devs = libxl__realloc(NOGC, *devs,
+ dt->dev_elem_size * (*num_dev + 1));
+ item = libxl__device_type_get_elem(dt, d_config, *num_dev);
+ (*num_dev)++;
+ } else {
+ dt->dispose(item);
+ }
+
+ dt->init(item);
+ dt->copy(CTX, item, type);
+}
+
+void libxl__device_add_async(libxl__egc *egc, uint32_t domid,
+ const struct libxl_device_type *dt, void *type,
+ libxl__ao_device *aodev)
+{
+ STATE_AO_GC(aodev->ao);
+ flexarray_t *back;
+ flexarray_t *front, *ro_front;
+ libxl__device *device;
+ xs_transaction_t t = XBT_NULL;
+ libxl_domain_config d_config;
+ void *type_saved;
+ libxl__domain_userdata_lock *lock = NULL;
+ int rc;
+
+ libxl_domain_config_init(&d_config);
+
+ type_saved = libxl__malloc(gc, dt->dev_elem_size);
+
+ dt->init(type_saved);
+ dt->copy(CTX, type_saved, type);
+
+ if (dt->set_default) {
+ rc = dt->set_default(gc, domid, type, aodev->update_json);
+ if (rc) goto out;
+ }
+
+ if (dt->update_devid) {
+ rc = dt->update_devid(gc, domid, type);
+ if (rc) goto out;
+ }
+
+ if (dt->update_config)
+ dt->update_config(gc, type_saved, type);
+
+ GCNEW(device);
+ rc = dt->to_device(gc, domid, type, device);
+ if (rc) goto out;
+
+ if (aodev->update_json) {
+ lock = libxl__lock_domain_userdata(gc, domid);
+ if (!lock) {
+ rc = ERROR_LOCK_FAIL;
+ goto out;
+ }
+
+ rc = libxl__get_domain_configuration(gc, domid, &d_config);
+ if (rc) goto out;
+
+ device_add_domain_config(gc, &d_config, dt, type_saved);
+
+ rc = libxl__dm_check_start(gc, &d_config, domid);
+ if (rc) goto out;
+ }
+
+ back = flexarray_make(gc, 16, 1);
+ front = flexarray_make(gc, 16, 1);
+ ro_front = flexarray_make(gc, 16, 1);
+
+ flexarray_append_pair(back, "frontend-id", GCSPRINTF("%d", domid));
+ flexarray_append_pair(back, "online", "1");
+ flexarray_append_pair(back, "state",
+ GCSPRINTF("%d", XenbusStateInitialising));
+
+ flexarray_append_pair(front, "backend-id",
+ GCSPRINTF("%d", device->backend_domid));
+ flexarray_append_pair(front, "state",
+ GCSPRINTF("%d", XenbusStateInitialising));
+
+ if (dt->set_xenstore_config)
+ dt->set_xenstore_config(gc, domid, type, back, front, ro_front);
+
+ for (;;) {
+ rc = libxl__xs_transaction_start(gc, &t);
+ if (rc) goto out;
+
+ rc = libxl__device_exists(gc, t, device);
+ if (rc < 0) goto out;
+ if (rc == 1) { /* already exists in xenstore */
+ LOGD(ERROR, domid, "device already exists in xenstore");
+ aodev->action = LIBXL__DEVICE_ACTION_ADD; /* for error message */
+ rc = ERROR_DEVICE_EXISTS;
+ goto out;
+ }
+
+ if (aodev->update_json) {
+ rc = libxl__set_domain_configuration(gc, domid, &d_config);
+ if (rc) goto out;
+ }
+
+ libxl__device_generic_add(gc, t, device,
+ libxl__xs_kvs_of_flexarray(gc, back),
+ libxl__xs_kvs_of_flexarray(gc, front),
+ libxl__xs_kvs_of_flexarray(gc, ro_front));
+
+ rc = libxl__xs_transaction_commit(gc, &t);
+ if (!rc) break;
+ if (rc < 0) goto out;
+ }
+
+ aodev->dev = device;
+ aodev->action = LIBXL__DEVICE_ACTION_ADD;
+ libxl__wait_device_connection(egc, aodev);
+
+ rc = 0;
+
+out:
+ libxl__xs_transaction_abort(gc, &t);
+ if (lock) libxl__unlock_domain_userdata(lock);
+ dt->dispose(type_saved);
+ libxl_domain_config_dispose(&d_config);
+ aodev->rc = rc;
+ if (rc) aodev->callback(egc, aodev);
+ return;
+}
+
+int libxl__device_add(libxl__gc *gc, uint32_t domid,
+ const struct libxl_device_type *dt, void *type)
+{
+ flexarray_t *back;
+ flexarray_t *front, *ro_front;
+ libxl__device *device;
+ int rc;
+
+ if (dt->set_default) {
+ rc = dt->set_default(gc, domid, type, false);
+ if (rc) goto out;
+ }
+
+ if (dt->update_devid) {
+ rc = dt->update_devid(gc, domid, type);
+ if (rc) goto out;
+ }
+
+ GCNEW(device);
+ rc = dt->to_device(gc, domid, type, device);
+ if (rc) goto out;
+
+ back = flexarray_make(gc, 16, 1);
+ front = flexarray_make(gc, 16, 1);
+ ro_front = flexarray_make(gc, 16, 1);
+
+ flexarray_append_pair(back, "frontend-id", GCSPRINTF("%d", domid));
+ flexarray_append_pair(back, "online", "1");
+ flexarray_append_pair(back, "state",
+ GCSPRINTF("%d", XenbusStateInitialising));
+ flexarray_append_pair(front, "backend-id",
+ libxl__sprintf(gc, "%d", device->backend_domid));
+ flexarray_append_pair(front, "state",
+ GCSPRINTF("%d", XenbusStateInitialising));
+
+ if (dt->set_xenstore_config)
+ dt->set_xenstore_config(gc, domid, type, back, front, ro_front);
+
+ rc = libxl__device_generic_add(gc, XBT_NULL, device,
+ libxl__xs_kvs_of_flexarray(gc, back),
+ libxl__xs_kvs_of_flexarray(gc, front),
+ libxl__xs_kvs_of_flexarray(gc, ro_front));
+ if (rc) goto out;
+
+ rc = 0;
+
+out:
+ return rc;
+}
+
/*
* Local variables:
* mode: C
GC_FREE;
}
-int libxl__device_disk_setdefault(libxl__gc *gc, libxl_device_disk *disk,
- uint32_t domid)
+int libxl__device_disk_setdefault(libxl__gc *gc, uint32_t domid,
+ libxl_device_disk *disk, bool hotplug)
{
int rc;
}
}
- rc = libxl__device_disk_setdefault(gc, disk, domid);
+ rc = libxl__device_disk_setdefault(gc, domid, disk, aodev->update_json);
if (rc) goto out;
front = flexarray_make(gc, 16, 1);
disk_empty.vdev = libxl__strdup(NOGC, disk->vdev);
disk_empty.pdev_path = libxl__strdup(NOGC, "");
disk_empty.is_cdrom = 1;
- libxl__device_disk_setdefault(gc, &disk_empty, domid);
+ libxl__device_disk_setdefault(gc, domid, &disk_empty, false);
libxl_domain_type type = libxl__domain_type(gc, domid);
if (type == LIBXL_DOMAIN_TYPE_INVALID) {
goto out;
}
- rc = libxl__device_disk_setdefault(gc, disk, domid);
+ rc = libxl__device_disk_setdefault(gc, domid, disk, false);
if (rc) goto out;
if (!disk->pdev_path) {
disk->script = libxl__strdup(gc, in_disk->script);
disk->vdev = NULL;
- rc = libxl__device_disk_setdefault(gc, disk, LIBXL_TOOLSTACK_DOMID);
+ rc = libxl__device_disk_setdefault(gc, LIBXL_TOOLSTACK_DOMID, disk,
+ false);
if (rc) goto out;
libxl__prepare_ao_device(ao, &dls->aodev);
elem->backend_domid == domid;
}
+#define libxl__device_disk_update_devid NULL
+
DEFINE_DEVICE_TYPE_STRUCT(disk,
.merge = libxl_device_disk_merge,
.dm_needed = libxl_device_disk_dm_needed,
* called libxl_device_nic_add at this point, but qemu needs
* the nic information to be complete.
*/
- ret = libxl__device_nic_setdefault(gc, &dm_config->nics[i], dm_domid,
+ ret = libxl__device_nic_setdefault(gc, dm_domid, &dm_config->nics[i],
false);
if (ret)
goto out;
libxl_domain_create_info *c_info);
_hidden int libxl__domain_build_info_setdefault(libxl__gc *gc,
libxl_domain_build_info *b_info);
-_hidden int libxl__device_disk_setdefault(libxl__gc *gc,
+_hidden int libxl__device_disk_setdefault(libxl__gc *gc, uint32_t domid,
libxl_device_disk *disk,
- uint32_t domid);
-_hidden int libxl__device_nic_setdefault(libxl__gc *gc, libxl_device_nic *nic,
- uint32_t domid, bool hotplug);
+ bool hotplug);
+_hidden int libxl__device_nic_setdefault(libxl__gc *gc, uint32_t domid,
+ libxl_device_nic *nic, bool hotplug);
_hidden int libxl__device_vfb_setdefault(libxl__gc *gc, libxl_device_vfb *vfb);
_hidden int libxl__device_vkb_setdefault(libxl__gc *gc, libxl_device_vkb *vkb);
-_hidden int libxl__device_pci_setdefault(libxl__gc *gc, libxl_device_pci *pci);
_hidden void libxl__rdm_setdefault(libxl__gc *gc,
libxl_domain_build_info *b_info);
_hidden int libxl__device_p9_setdefault(libxl__gc *gc,
return AO_INPROGRESS; \
}
+#define LIBXL_DEFINE_UPDATE_DEVID(type, name) \
+ int libxl__device_##type##_update_devid(libxl__gc *gc, \
+ uint32_t domid, \
+ libxl_device_##type *type) \
+ { \
+ if (type->devid == -1) \
+ type->devid = libxl__device_nextid(gc, domid, name); \
+ if (type->devid < 0) \
+ return ERROR_FAIL; \
+ return 0; \
+ }
+
#define LIBXL_DEFINE_DEVICE_REMOVE(type) \
LIBXL_DEFINE_DEVICE_REMOVE_EXT(type, generic, remove, 0) \
LIBXL_DEFINE_DEVICE_REMOVE_EXT(type, generic, destroy, 1)
void (*add)(libxl__egc *, libxl__ao *, uint32_t, libxl_domain_config *,
libxl__multidev *);
void *(*list)(libxl_ctx *, uint32_t, int *);
+ int (*set_default)(libxl__gc *, uint32_t, void *, bool);
+ int (*to_device)(libxl__gc *, uint32_t, void *, libxl__device *);
+ void (*init)(void *);
+ void (*copy)(libxl_ctx *, void *, void *);
void (*dispose)(void *);
int (*compare)(void *, void *);
void (*merge)(libxl_ctx *, void *, void *);
int (*dm_needed)(void *, unsigned);
void (*update_config)(libxl__gc *, void *, void *);
+ int (*update_devid)(libxl__gc *, uint32_t, void *);
+ int (*set_xenstore_config)(libxl__gc *, uint32_t, void *, flexarray_t *,
+ flexarray_t *, flexarray_t *);
};
#define DEFINE_DEVICE_TYPE_STRUCT_X(name, sname, ...) \
.add = libxl__add_ ## name ## s, \
.list = (void *(*)(libxl_ctx *, uint32_t, int *)) \
libxl_device_ ## sname ## _list, \
+ .set_default = (int (*)(libxl__gc *, uint32_t, void *, bool))\
+ libxl__device_ ## sname ## _setdefault, \
+ .to_device = (int (*)(libxl__gc *, uint32_t, \
+ void *, libxl__device *)) \
+ libxl__device_from_ ## name, \
+ .init = (void (*)(void *))libxl_device_ ## sname ## _init, \
+ .copy = (void (*)(libxl_ctx *, void *, void *)) \
+ libxl_device_ ## sname ## _copy, \
.dispose = (void (*)(void *))libxl_device_ ## sname ## _dispose, \
.compare = (int (*)(void *, void *)) \
libxl_device_ ## sname ## _compare, \
+ .update_devid = (int (*)(libxl__gc *, uint32_t, void *)) \
+ libxl__device_ ## sname ## _update_devid, \
__VA_ARGS__ \
}
return libxl_defbool_val(b_info->acpi) &&
libxl_defbool_val(b_info->u.hvm.acpi);
}
+
+void libxl__device_add_async(libxl__egc *egc, uint32_t domid,
+ const struct libxl_device_type *dt, void *type,
+ libxl__ao_device *aodev);
+int libxl__device_add(libxl__gc *gc, uint32_t domid,
+ const struct libxl_device_type *dt, void *type);
+
#endif
/*
return rc;
}
-int libxl__device_nic_setdefault(libxl__gc *gc, libxl_device_nic *nic,
- uint32_t domid, bool hotplug)
+int libxl__device_nic_setdefault(libxl__gc *gc, uint32_t domid,
+ libxl_device_nic *nic, bool hotplug)
{
int rc;
libxl_mac_copy(CTX, &dst->mac, &src->mac);
}
+static LIBXL_DEFINE_UPDATE_DEVID(nic, "vif")
+
static void libxl__device_nic_add(libxl__egc *egc, uint32_t domid,
libxl_device_nic *nic,
libxl__ao_device *aodev)
libxl_device_nic_init(&nic_saved);
libxl_device_nic_copy(CTX, &nic_saved, nic);
- rc = libxl__device_nic_setdefault(gc, nic, domid, aodev->update_json);
+ rc = libxl__device_nic_setdefault(gc, domid, nic, aodev->update_json);
if (rc) goto out;
front = flexarray_make(gc, 16, 1);
back = flexarray_make(gc, 18, 1);
- if (nic->devid == -1) {
- if ((nic->devid = libxl__device_nextid(gc, domid, "vif")) < 0) {
- rc = ERROR_FAIL;
- goto out;
- }
- }
+ rc = libxl__device_nic_update_devid(gc, domid, nic);
+ if (rc) goto out;
libxl__update_config_nic(gc, &nic_saved, nic);
* called libxl_device_nic_add when domcreate_launch_dm gets called,
* but qemu needs the nic information to be complete.
*/
- ret = libxl__device_nic_setdefault(gc, &d_config->nics[i], domid,
+ ret = libxl__device_nic_setdefault(gc, domid, &d_config->nics[i],
false);
if (ret) {
LOGD(ERROR, domid, "Unable to set nic defaults for nic %d", i);
return -1;
}
-int libxl__device_pci_setdefault(libxl__gc *gc, libxl_device_pci *pci)
+static int libxl__device_pci_setdefault(libxl__gc *gc, uint32_t domid,
+ libxl_device_pci *pci, bool hotplug)
{
/* We'd like to force reserve rdm specific to a device by default.*/
if (pci->rdm_policy == LIBXL_RDM_RESERVE_POLICY_INVALID)
}
}
- rc = libxl__device_pci_setdefault(gc, pcidev);
+ rc = libxl__device_pci_setdefault(gc, domid, pcidev, false);
if (rc) goto out;
if (pcidev->seize && !pciback_dev_is_assigned(gc, pcidev)) {
return COMPARE_PCI(d1, d2);
}
+#define libxl__device_pci_update_devid NULL
+
DEFINE_DEVICE_TYPE_STRUCT_X(pcidev, pci);
/*
}
static int libxl__device_usbctrl_setdefault(libxl__gc *gc, uint32_t domid,
- libxl_device_usbctrl *usbctrl)
+ libxl_device_usbctrl *usbctrl,
+ bool hotplug)
{
int rc;
libxl_domain_type domtype = libxl__domain_type(gc, domid);
return libxl__qmp_run_command_flexarray(gc, domid, "device_del", qmp_args);
}
+static LIBXL_DEFINE_UPDATE_DEVID(usbctrl, "vusb")
+
/* AO operation to add a usb controller.
*
* Generally, it does:
libxl__device *device;
int rc;
- rc = libxl__device_usbctrl_setdefault(gc, domid, usbctrl);
+ rc = libxl__device_usbctrl_setdefault(gc, domid, usbctrl,
+ aodev->update_json);
if (rc < 0) goto out;
- if (usbctrl->devid == -1) {
- usbctrl->devid = libxl__device_nextid(gc, domid, "vusb");
- if (usbctrl->devid < 0) {
- rc = ERROR_FAIL;
- goto out;
- }
- }
+ rc = libxl__device_usbctrl_update_devid(gc, domid, usbctrl);
+ if (rc) goto out;
rc = libxl__device_usbctrl_add_xenstore(gc, domid, usbctrl,
aodev->update_json);
GCNEW(usbctrl);
libxl_device_usbctrl_init(usbctrl);
- rc = libxl__device_usbctrl_setdefault(gc, domid, usbctrl);
+ rc = libxl__device_usbctrl_setdefault(gc, domid, usbctrl,
+ update_json);
if (rc < 0) goto out;
- if (usbctrl->devid == -1) {
- usbctrl->devid = libxl__device_nextid(gc, domid, "vusb");
- if (usbctrl->devid < 0) {
- rc = ERROR_FAIL;
- goto out;
- }
- }
+ rc = libxl__device_usbctrl_update_devid(gc, domid, usbctrl);
+ if (rc) goto out;
rc = libxl__device_usbctrl_add_xenstore(gc, domid, usbctrl,
update_json);
free(list);
}
+#define libxl__device_usbctrl_update_devid NULL
+
DEFINE_DEVICE_TYPE_STRUCT(usbctrl,
.dm_needed = libxl_device_usbctrl_dm_needed
);
+
+#define libxl__device_from_usbdev NULL
+#define libxl__device_usbdev_update_devid NULL
+
DEFINE_DEVICE_TYPE_STRUCT(usbdev);
/*
#include "libxl_internal.h"
-static int libxl__device_vtpm_setdefault(libxl__gc *gc, libxl_device_vtpm *vtpm)
+static int libxl__device_vtpm_setdefault(libxl__gc *gc, uint32_t domid,
+ libxl_device_vtpm *vtpm, bool hotplug)
{
int rc;
if (libxl_uuid_is_nil(&vtpm->uuid)) {
libxl_uuid_copy(CTX, &dst->uuid, &src->uuid);
}
+static LIBXL_DEFINE_UPDATE_DEVID(vtpm, "vtpm")
+
static void libxl__device_vtpm_add(libxl__egc *egc, uint32_t domid,
libxl_device_vtpm *vtpm,
libxl__ao_device *aodev)
libxl_device_vtpm_init(&vtpm_saved);
libxl_device_vtpm_copy(CTX, &vtpm_saved, vtpm);
- rc = libxl__device_vtpm_setdefault(gc, vtpm);
+ rc = libxl__device_vtpm_setdefault(gc, domid, vtpm, aodev->update_json);
if (rc) goto out;
front = flexarray_make(gc, 16, 1);
back = flexarray_make(gc, 16, 1);
- if (vtpm->devid == -1) {
- if ((vtpm->devid = libxl__device_nextid(gc, domid, "vtpm")) < 0) {
- rc = ERROR_FAIL;
- goto out;
- }
- }
+ rc = libxl__device_vtpm_update_devid(gc, domid, vtpm);
+ if (rc) goto out;
libxl__update_config_vtpm(gc, &vtpm_saved, vtpm);