static int libxl_build_xenpv_qemu_args(libxl__gc *gc, uint32_t domid, libxl_device_vfb *vfb, libxl_device_model_info *info) { libxl_ctx *ctx = libxl__gc_owner(gc); memset(info, 0x00, sizeof(libxl_device_model_info)); if (vfb != NULL) { info->vnc = vfb->vnc; if (vfb->vnclisten) info->vnclisten = libxl__strdup(gc, vfb->vnclisten); info->vncdisplay = vfb->vncdisplay; info->vncunused = vfb->vncunused; if (vfb->vncpasswd) info->vncpasswd = vfb->vncpasswd; if (vfb->keymap) info->keymap = libxl__strdup(gc, vfb->keymap); info->sdl = vfb->sdl; info->opengl = vfb->opengl; } else info->nographic = 1; info->domid = domid; info->dom_name = libxl_domid_to_name(ctx, domid); info->device_model = libxl__abs_path(gc, "qemu-dm", libxl_libexec_path()); info->type = XENPV; return 0; }
/* * the script needs the following env & args * $vifname * $XENBUS_PATH (/libxl/<domid>/remus/netbuf/<devid>/) * $REMUS_IFB (for teardown) * setup/teardown as command line arg. */ static void setup_async_exec(libxl__checkpoint_device *dev, char *op) { int arraysize, nr = 0; char **env = NULL, **args = NULL; libxl__remus_device_nic *remus_nic = dev->concrete_data; libxl__checkpoint_devices_state *cds = dev->cds; libxl__async_exec_state *aes = &dev->aodev.aes; libxl__remus_state *rs = cds->concrete_data; STATE_AO_GC(cds->ao); /* Convenience aliases */ char *const script = libxl__strdup(gc, rs->netbufscript); const uint32_t domid = cds->domid; const int dev_id = remus_nic->devid; const char *const vif = remus_nic->vif; const char *const ifb = remus_nic->ifb; arraysize = 7; GCNEW_ARRAY(env, arraysize); env[nr++] = "vifname"; env[nr++] = libxl__strdup(gc, vif); env[nr++] = "XENBUS_PATH"; env[nr++] = GCSPRINTF("%s/remus/netbuf/%d", libxl__xs_libxl_path(gc, domid), dev_id); if (!strcmp(op, "teardown") && ifb) { env[nr++] = "REMUS_IFB"; env[nr++] = libxl__strdup(gc, ifb); } env[nr++] = NULL; assert(nr <= arraysize); arraysize = 3; nr = 0; GCNEW_ARRAY(args, arraysize); args[nr++] = script; args[nr++] = op; args[nr++] = NULL; assert(nr == arraysize); aes->ao = dev->cds->ao; aes->what = GCSPRINTF("%s %s", args[0], args[1]); aes->env = env; aes->args = args; aes->timeout_ms = LIBXL_HOTPLUG_TIMEOUT * 1000; aes->stdfds[0] = -1; aes->stdfds[1] = -1; aes->stdfds[2] = -1; if (!strcmp(op, "teardown")) aes->callback = netbuf_teardown_script_cb; else aes->callback = netbuf_setup_script_cb; }
const char *libxl__domain_device_model(libxl__gc *gc, const libxl_domain_build_info *info) { libxl_ctx *ctx = libxl__gc_owner(gc); const char *dm; if (libxl_defbool_val(info->device_model_stubdomain)) return NULL; if (info->device_model) { dm = libxl__strdup(gc, info->device_model); } else { switch (info->device_model_version) { case LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN_TRADITIONAL: dm = libxl__abs_path(gc, "qemu-dm", libxl__libexec_path()); break; case LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN: dm = qemu_xen_path(gc); break; default: LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "invalid device model version %d\n", info->device_model_version); dm = NULL; break; } } return dm; }
static const char *libxl_tapif_script(libxl__gc *gc) { #ifdef __linux__ return libxl__strdup(gc, "no"); #else return libxl__sprintf(gc, "%s/qemu-ifup", libxl__xen_script_dir_path()); #endif }
char *libxl__dirname(libxl__gc *gc, const char *s) { char *c; char *ptr = libxl__strdup(gc, s); c = strrchr(ptr, '/'); if (!c) return NULL; *c = '\0'; return ptr; }
int init_subkind_nic(libxl__checkpoint_devices_state *cds) { int rc, ret; libxl__domain_save_state *dss = CONTAINER_OF(cds, *dss, cds); libxl__remus_state *rs = cds->concrete_data; STATE_AO_GC(cds->ao); rs->nlsock = nl_socket_alloc(); if (!rs->nlsock) { LOGD(ERROR, dss->domid, "cannot allocate nl socket"); rc = ERROR_FAIL; goto out; } ret = nl_connect(rs->nlsock, NETLINK_ROUTE); if (ret) { LOGD(ERROR, dss->domid, "failed to open netlink socket: %s", nl_geterror(ret)); rc = ERROR_FAIL; goto out; } /* get list of all qdiscs installed on network devs. */ ret = rtnl_qdisc_alloc_cache(rs->nlsock, &rs->qdisc_cache); if (ret) { LOGD(ERROR, dss->domid, "failed to allocate qdisc cache: %s", nl_geterror(ret)); rc = ERROR_FAIL; goto out; } if (dss->remus->netbufscript) { rs->netbufscript = libxl__strdup(gc, dss->remus->netbufscript); } else { rs->netbufscript = GCSPRINTF("%s/remus-netbuf-setup", libxl__xen_script_dir_path()); } rc = 0; out: return rc; }
int libxl_device_nic_getinfo(libxl_ctx *ctx, uint32_t domid, libxl_device_nic *nic, libxl_nicinfo *nicinfo) { GC_INIT(ctx); char *dompath, *nicpath, *libxl_path; char *val; int rc; dompath = libxl__xs_get_dompath(gc, domid); nicinfo->devid = nic->devid; nicpath = GCSPRINTF("%s/device/vif/%d", dompath, nicinfo->devid); libxl_path = GCSPRINTF("%s/device/vif/%d", libxl__xs_libxl_path(gc, domid), nicinfo->devid); nicinfo->backend = xs_read(ctx->xsh, XBT_NULL, GCSPRINTF("%s/backend", libxl_path), NULL); if (!nicinfo->backend) { GC_FREE; return ERROR_FAIL; } rc = libxl__backendpath_parse_domid(gc, nicinfo->backend, &nicinfo->backend_id); if (rc) goto out; val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/state", nicpath)); nicinfo->state = val ? strtoul(val, NULL, 10) : -1; val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/event-channel", nicpath)); nicinfo->evtch = val ? strtoul(val, NULL, 10) : -1; val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/tx-ring-ref", nicpath)); nicinfo->rref_tx = val ? strtoul(val, NULL, 10) : -1; val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/rx-ring-ref", nicpath)); nicinfo->rref_rx = val ? strtoul(val, NULL, 10) : -1; nicinfo->frontend = libxl__strdup(NOGC, nicpath); nicinfo->frontend_id = domid; rc = 0; out: GC_FREE; return rc; }
static int parse_bootloader_result(libxl__egc *egc, libxl__bootloader_state *bl) { STATE_AO_GC(bl->ao); char buf[PATH_MAX*2]; FILE *f = 0; int rc = ERROR_FAIL; f = fopen(bl->outputpath, "r"); if (!f) { LOGE(ERROR,"open bootloader output file %s", bl->outputpath); goto out; } for (;;) { /* Read a nul-terminated "line" and put the result in * buf, and its length (not including the nul) in l */ int l = 0, c; while ((c = getc(f)) != EOF && c != '\0') { if (l < sizeof(buf)-1) buf[l] = c; l++; } if (c == EOF) { if (ferror(f)) { LOGE(ERROR,"read bootloader output file %s", bl->outputpath); goto out; } if (!l) break; } if (l >= sizeof(buf)) { LOG(WARN,"bootloader output contained" " overly long item `%.150s...'", buf); continue; } buf[l] = 0; const char *rhs; #define COMMAND(s) ((rhs = bootloader_result_command(gc, buf, s, sizeof(s)-1))) if (COMMAND("kernel")) { bl->kernel->path = libxl__strdup(gc, rhs); libxl__file_reference_map(bl->kernel); unlink(bl->kernel->path); } else if (COMMAND("ramdisk")) { bl->ramdisk->path = libxl__strdup(gc, rhs); libxl__file_reference_map(bl->ramdisk); unlink(bl->ramdisk->path); } else if (COMMAND("args")) { bl->cmdline = libxl__strdup(gc, rhs); } else if (l) { LOG(WARN, "unexpected output from bootloader: `%s'", buf); } } rc = 0; out: if (f) fclose(f); return rc; }
/* Portability note: this lock utilises flock(2) so a proper implementation of * flock(2) is required. */ libxl__domain_userdata_lock *libxl__lock_domain_userdata(libxl__gc *gc, uint32_t domid) { libxl__domain_userdata_lock *lock = NULL; const char *lockfile; int fd; struct stat stab, fstab; lockfile = libxl__userdata_path(gc, domid, "domain-userdata-lock", "l"); if (!lockfile) goto out; lock = libxl__zalloc(NOGC, sizeof(libxl__domain_userdata_lock)); lock->path = libxl__strdup(NOGC, lockfile); while (true) { libxl__carefd_begin(); fd = open(lockfile, O_RDWR|O_CREAT, 0666); if (fd < 0) LOGE(ERROR, "cannot open lockfile %s, errno=%d", lockfile, errno); lock->lock_carefd = libxl__carefd_opened(CTX, fd); if (fd < 0) goto out; /* Lock the file in exclusive mode, wait indefinitely to * acquire the lock */ while (flock(fd, LOCK_EX)) { switch (errno) { case EINTR: /* Signal received, retry */ continue; default: /* All other errno: EBADF, EINVAL, ENOLCK, EWOULDBLOCK */ LOGE(ERROR, "unexpected error while trying to lock %s, fd=%d, errno=%d", lockfile, fd, errno); goto out; } } if (fstat(fd, &fstab)) { LOGE(ERROR, "cannot fstat %s, fd=%d, errno=%d", lockfile, fd, errno); goto out; } if (stat(lockfile, &stab)) { if (errno != ENOENT) { LOGE(ERROR, "cannot stat %s, errno=%d", lockfile, errno); goto out; } } else { if (stab.st_dev == fstab.st_dev && stab.st_ino == fstab.st_ino) break; } libxl__carefd_close(lock->lock_carefd); } /* Check the domain is still there, if not we should release the * lock and clean up. */ if (libxl_domain_info(CTX, NULL, domid)) goto out; return lock; out: if (lock) libxl__unlock_domain_userdata(lock); return NULL; }
char *libxl__abs_path(libxl__gc *gc, const char *s, const char *path) { if (!s || s[0] == '/') return libxl__strdup(gc, s); return libxl__sprintf(gc, "%s/%s", path, s); }
void libxl__colo_restore_setup(libxl__egc *egc, libxl__colo_restore_state *crs) { libxl__domain_create_state *dcs = CONTAINER_OF(crs, *dcs, crs); libxl__colo_restore_checkpoint_state *crcs; int rc = ERROR_FAIL; /* Convenience aliases */ libxl__srm_restore_autogen_callbacks *const callbacks = &dcs->srs.shs.callbacks.restore.a; const int domid = crs->domid; STATE_AO_GC(crs->ao); GCNEW(crcs); crs->crcs = crcs; crcs->crs = crs; crs->qdisk_setuped = false; crs->qdisk_used = false; if (dcs->colo_proxy_script) crs->colo_proxy_script = libxl__strdup(gc, dcs->colo_proxy_script); else crs->colo_proxy_script = GCSPRINTF("%s/colo-proxy-setup", libxl__xen_script_dir_path()); /* setup dsps */ crcs->dsps.ao = ao; crcs->dsps.domid = domid; if (init_dsps(&crcs->dsps)) goto out; callbacks->postcopy = libxl__colo_restore_domain_resume_callback; callbacks->wait_checkpoint = libxl__colo_restore_domain_wait_checkpoint_callback; callbacks->suspend = libxl__colo_restore_domain_suspend_callback; callbacks->checkpoint = libxl__colo_restore_domain_checkpoint_callback; /* * Secondary vm is running in colo mode, so we need to call * libxl__xc_domain_restore_done() to create secondary vm. * But we will exit in domain_create_cb(). So replace the * callback here. */ crs->saved_cb = dcs->callback; dcs->callback = libxl__colo_domain_create_cb; crcs->state_file = GCSPRINTF(LIBXL_DEVICE_MODEL_RESTORE_FILE".%d", domid); crcs->status = LIBXL_COLO_SETUPED; libxl__logdirty_init(&crcs->lds); crcs->lds.ao = ao; crcs->sws.fd = crs->send_back_fd; crcs->sws.ao = ao; crcs->sws.back_channel = true; dcs->cds.concrete_data = crs; libxl__stream_write_start(egc, &crcs->sws); rc = 0; out: crs->callback(egc, crs, rc); return; }
int libxl__domain_build_info_setdefault(libxl__gc *gc, libxl_domain_build_info *b_info) { if (b_info->type != LIBXL_DOMAIN_TYPE_HVM && b_info->type != LIBXL_DOMAIN_TYPE_PV) return ERROR_INVAL; libxl_defbool_setdefault(&b_info->device_model_stubdomain, false); if (!b_info->device_model_version) { if (b_info->type == LIBXL_DOMAIN_TYPE_HVM) b_info->device_model_version = LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN_TRADITIONAL; else { const char *dm; int rc; b_info->device_model_version = LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN; dm = libxl__domain_device_model(gc, b_info); rc = access(dm, X_OK); if (rc < 0) { /* qemu-xen unavailable, use qemu-xen-traditional */ if (errno == ENOENT) { LIBXL__LOG_ERRNO(CTX, XTL_VERBOSE, "qemu-xen is unavailable" ", use qemu-xen-traditional instead"); b_info->device_model_version = LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN_TRADITIONAL; } else { LIBXL__LOG_ERRNO(CTX, XTL_ERROR, "qemu-xen access error"); return ERROR_FAIL; } } } } if (b_info->blkdev_start == NULL) b_info->blkdev_start = libxl__strdup(NOGC, "xvda"); if (b_info->type == LIBXL_DOMAIN_TYPE_HVM) { if (!b_info->u.hvm.bios) switch (b_info->device_model_version) { case LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN_TRADITIONAL: b_info->u.hvm.bios = LIBXL_BIOS_TYPE_ROMBIOS; break; case LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN: b_info->u.hvm.bios = LIBXL_BIOS_TYPE_SEABIOS; break; default:return ERROR_INVAL; } /* Enforce BIOS<->Device Model version relationship */ switch (b_info->device_model_version) { case LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN_TRADITIONAL: if (b_info->u.hvm.bios != LIBXL_BIOS_TYPE_ROMBIOS) return ERROR_INVAL; break; case LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN: if (b_info->u.hvm.bios == LIBXL_BIOS_TYPE_ROMBIOS) return ERROR_INVAL; break; default:abort(); } } if (b_info->type == LIBXL_DOMAIN_TYPE_HVM && b_info->device_model_version != LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN_TRADITIONAL && libxl_defbool_val(b_info->device_model_stubdomain)) { LIBXL__LOG(CTX, XTL_ERROR, "device model stubdomains require \"qemu-xen-traditional\""); return ERROR_INVAL; } if (!b_info->max_vcpus) b_info->max_vcpus = 1; if (!b_info->avail_vcpus.size) { if (libxl_cpu_bitmap_alloc(CTX, &b_info->avail_vcpus, 1)) return ERROR_FAIL; libxl_bitmap_set(&b_info->avail_vcpus, 0); } else if (b_info->avail_vcpus.size > HVM_MAX_VCPUS) return ERROR_FAIL; if (!b_info->cpumap.size) { if (libxl_cpu_bitmap_alloc(CTX, &b_info->cpumap, 0)) return ERROR_FAIL; libxl_bitmap_set_any(&b_info->cpumap); } libxl_defbool_setdefault(&b_info->numa_placement, true); if (b_info->max_memkb == LIBXL_MEMKB_DEFAULT) b_info->max_memkb = 32 * 1024; if (b_info->target_memkb == LIBXL_MEMKB_DEFAULT) b_info->target_memkb = b_info->max_memkb; libxl_defbool_setdefault(&b_info->localtime, false); libxl_defbool_setdefault(&b_info->disable_migrate, false); switch (b_info->type) { case LIBXL_DOMAIN_TYPE_HVM: if (b_info->shadow_memkb == LIBXL_MEMKB_DEFAULT) b_info->shadow_memkb = 0; if (b_info->video_memkb == LIBXL_MEMKB_DEFAULT) b_info->video_memkb = 8 * 1024; if (b_info->u.hvm.timer_mode == LIBXL_TIMER_MODE_DEFAULT) b_info->u.hvm.timer_mode = LIBXL_TIMER_MODE_NO_DELAY_FOR_MISSED_TICKS; libxl_defbool_setdefault(&b_info->u.hvm.pae, true); libxl_defbool_setdefault(&b_info->u.hvm.apic, true); libxl_defbool_setdefault(&b_info->u.hvm.acpi, true); libxl_defbool_setdefault(&b_info->u.hvm.acpi_s3, true); libxl_defbool_setdefault(&b_info->u.hvm.acpi_s4, true); libxl_defbool_setdefault(&b_info->u.hvm.nx, true); libxl_defbool_setdefault(&b_info->u.hvm.viridian, false); libxl_defbool_setdefault(&b_info->u.hvm.hpet, true); libxl_defbool_setdefault(&b_info->u.hvm.vpt_align, true); libxl_defbool_setdefault(&b_info->u.hvm.nested_hvm, false); libxl_defbool_setdefault(&b_info->u.hvm.usb, false); libxl_defbool_setdefault(&b_info->u.hvm.xen_platform_pci, true); if (!b_info->u.hvm.boot) { b_info->u.hvm.boot = strdup("cda"); if (!b_info->u.hvm.boot) return ERROR_NOMEM; } if (!b_info->u.hvm.vga.kind) b_info->u.hvm.vga.kind = LIBXL_VGA_INTERFACE_TYPE_CIRRUS; libxl_defbool_setdefault(&b_info->u.hvm.vnc.enable, true); if (libxl_defbool_val(b_info->u.hvm.vnc.enable)) { libxl_defbool_setdefault(&b_info->u.hvm.vnc.findunused, true); if (!b_info->u.hvm.vnc.listen) { b_info->u.hvm.vnc.listen = strdup("127.0.0.1"); if (!b_info->u.hvm.vnc.listen) return ERROR_NOMEM; } } libxl_defbool_setdefault(&b_info->u.hvm.sdl.enable, false); if (libxl_defbool_val(b_info->u.hvm.sdl.enable)) { libxl_defbool_setdefault(&b_info->u.hvm.sdl.opengl, false); } libxl_defbool_setdefault(&b_info->u.hvm.spice.enable, false); if (libxl_defbool_val(b_info->u.hvm.spice.enable)) { libxl_defbool_setdefault(&b_info->u.hvm.spice.disable_ticketing, false); libxl_defbool_setdefault(&b_info->u.hvm.spice.agent_mouse, true); } libxl_defbool_setdefault(&b_info->u.hvm.nographic, false); libxl_defbool_setdefault(&b_info->u.hvm.gfx_passthru, false); break; case LIBXL_DOMAIN_TYPE_PV: libxl_defbool_setdefault(&b_info->u.pv.e820_host, false); if (b_info->shadow_memkb == LIBXL_MEMKB_DEFAULT) b_info->shadow_memkb = 0; if (b_info->u.pv.slack_memkb == LIBXL_MEMKB_DEFAULT) b_info->u.pv.slack_memkb = 0; break; default: LIBXL__LOG(CTX, LIBXL__LOG_ERROR, "invalid domain type %s in create info", libxl_domain_type_to_string(b_info->type)); return ERROR_INVAL; } return 0; }
void libxl__colo_save_setup(libxl__egc *egc, libxl__colo_save_state *css) { libxl__domain_save_state *dss = CONTAINER_OF(css, *dss, css); /* Convenience aliases */ libxl__checkpoint_devices_state *const cds = &dss->cds; libxl__srm_save_autogen_callbacks *const callbacks = &dss->sws.shs.callbacks.save.a; STATE_AO_GC(dss->ao); if (dss->type != LIBXL_DOMAIN_TYPE_HVM) { LOGD(ERROR, dss->domid, "COLO only supports hvm now"); goto out; } css->send_fd = dss->fd; css->recv_fd = dss->recv_fd; css->svm_running = false; css->paused = true; css->qdisk_setuped = false; css->qdisk_used = false; libxl__ev_child_init(&css->child); css->cps.is_userspace_proxy = libxl_defbool_val(dss->remus->userspace_colo_proxy); if (dss->remus->netbufscript) css->colo_proxy_script = libxl__strdup(gc, dss->remus->netbufscript); else css->colo_proxy_script = GCSPRINTF("%s/colo-proxy-setup", libxl__xen_script_dir_path()); cds->ops = colo_ops; cds->callback = colo_save_setup_done; cds->ao = ao; cds->domid = dss->domid; cds->concrete_data = css; /* If enable userspace proxy mode, we don't need VIF */ if (css->cps.is_userspace_proxy) { cds->device_kind_flags = (1 << LIBXL__DEVICE_KIND_VBD); /* Use this args we can connect to qemu colo-compare */ cds->nics = libxl__device_list(gc, &libxl__nic_devtype, cds->domid, &cds->num_nics); if (cds->num_nics > 0) { css->cps.checkpoint_host = cds->nics[0].colo_checkpoint_host; css->cps.checkpoint_port = cds->nics[0].colo_checkpoint_port; } } else { cds->device_kind_flags = (1 << LIBXL__DEVICE_KIND_VIF) | (1 << LIBXL__DEVICE_KIND_VBD); } css->srs.ao = ao; css->srs.fd = css->recv_fd; css->srs.back_channel = true; libxl__stream_read_start(egc, &css->srs); css->cps.ao = ao; if (colo_proxy_setup(&css->cps)) { LOGD(ERROR, cds->domid, "COLO: failed to setup colo proxy for guest"); goto out; } if (init_device_subkind(cds)) goto out; callbacks->suspend = libxl__colo_save_domain_suspend_callback; callbacks->checkpoint = libxl__colo_save_domain_checkpoint_callback; callbacks->postcopy = libxl__colo_save_domain_resume_callback; callbacks->wait_checkpoint = libxl__colo_save_domain_wait_checkpoint_callback; libxl__checkpoint_devices_setup(egc, &dss->cds); return; out: dss->callback(egc, dss, ERROR_FAIL); }
static void libxl__device_nic_add(libxl__egc *egc, uint32_t domid, libxl_device_nic *nic, libxl__ao_device *aodev) { STATE_AO_GC(aodev->ao); flexarray_t *front; flexarray_t *back; libxl__device *device; int rc; xs_transaction_t t = XBT_NULL; libxl_domain_config d_config; libxl_device_nic nic_saved; libxl__domain_userdata_lock *lock = NULL; libxl_domain_config_init(&d_config); 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); 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; } } libxl__update_config_nic(gc, &nic_saved, nic); GCNEW(device); rc = libxl__device_from_nic(gc, domid, nic, device); if ( rc != 0 ) goto out; flexarray_append(back, "frontend-id"); flexarray_append(back, GCSPRINTF("%d", domid)); flexarray_append(back, "online"); flexarray_append(back, "1"); flexarray_append(back, "state"); flexarray_append(back, GCSPRINTF("%d", XenbusStateInitialising)); if (nic->script) flexarray_append_pair(back, "script", libxl__abs_path(gc, nic->script, libxl__xen_script_dir_path())); if (nic->ifname) { flexarray_append(back, "vifname"); flexarray_append(back, nic->ifname); } if (nic->coloft_forwarddev) { flexarray_append(back, "forwarddev"); flexarray_append(back, nic->coloft_forwarddev); } flexarray_append(back, "mac"); flexarray_append(back,GCSPRINTF(LIBXL_MAC_FMT, LIBXL_MAC_BYTES(nic->mac))); if (nic->ip) { flexarray_append(back, "ip"); flexarray_append(back, libxl__strdup(gc, nic->ip)); } if (nic->gatewaydev) { flexarray_append(back, "gatewaydev"); flexarray_append(back, libxl__strdup(gc, nic->gatewaydev)); } if (nic->rate_interval_usecs > 0) { flexarray_append(back, "rate"); flexarray_append(back, GCSPRINTF("%"PRIu64",%"PRIu32"", nic->rate_bytes_per_interval, nic->rate_interval_usecs)); } flexarray_append(back, "bridge"); flexarray_append(back, libxl__strdup(gc, nic->bridge)); flexarray_append(back, "handle"); flexarray_append(back, GCSPRINTF("%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, GCSPRINTF("%d", nic->backend_domid)); flexarray_append(front, "state"); flexarray_append(front, GCSPRINTF("%d", XenbusStateInitialising)); flexarray_append(front, "handle"); flexarray_append(front, GCSPRINTF("%d", nic->devid)); flexarray_append(front, "mac"); flexarray_append(front, GCSPRINTF( LIBXL_MAC_FMT, LIBXL_MAC_BYTES(nic->mac))); 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(nic, nics, domid, &nic_saved, COMPARE_DEVID, &d_config); rc = libxl__dm_check_start(gc, &d_config, domid); if (rc) goto out; } 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 */ LOG(ERROR, "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, back->count), libxl__xs_kvs_of_flexarray(gc, front, front->count), NULL); 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); libxl_device_nic_dispose(&nic_saved); libxl_domain_config_dispose(&d_config); aodev->rc = rc; if (rc) aodev->callback(egc, aodev); return; }
char *libxl__abs_path(libxl__gc *gc, const char *s, const char *path) { if (s[0] == '/') return libxl__strdup(gc, s); return GCSPRINTF("%s/%s", path, s); }