/* * 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; }
/* Hotplug scripts caller functions */ static int libxl__hotplug(libxl__gc *gc, libxl__device *dev, char ***args, libxl__device_action action) { char *be_path = libxl__device_backend_path(gc, dev); char *script; int nr = 0, rc = 0, arraysize = 4; script = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/%s", be_path, "script")); if (!script) { LOGEV(ERROR, errno, "unable to read script from %s", be_path); rc = ERROR_FAIL; goto out; } GCNEW_ARRAY(*args, arraysize); (*args)[nr++] = script; (*args)[nr++] = be_path; (*args)[nr++] = GCSPRINTF("%d", action == LIBXL__DEVICE_ACTION_ADD ? XenbusStateInitWait : XenbusStateClosed); (*args)[nr++] = NULL; assert(nr == arraysize); out: return rc; }
static int libxl__hotplug_disk(libxl__gc *gc, libxl__device *dev, char ***args, char ***env, libxl__device_action action) { char *be_path = libxl__device_backend_path(gc, dev); char *script; int nr = 0, rc = 0; script = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/%s", be_path, "script")); if (!script) { LOGEV(ERROR, errno, "unable to read script from %s", be_path); rc = ERROR_FAIL; goto error; } *env = get_hotplug_env(gc, script, dev); if (!*env) { rc = ERROR_FAIL; goto error; } const int arraysize = 3; GCNEW_ARRAY(*args, arraysize); (*args)[nr++] = script; (*args)[nr++] = action == DEVICE_CONNECT ? "add" : "remove"; (*args)[nr++] = NULL; assert(nr == arraysize); rc = 1; error: return rc; }
/* Set the RTDS scheduling parameters of vcpu(s) */ static int sched_rtds_vcpu_set(libxl__gc *gc, uint32_t domid, const libxl_vcpu_sched_params *scinfo) { int r, rc; int i; uint16_t max_vcpuid; xc_dominfo_t info; struct xen_domctl_schedparam_vcpu *vcpus; r = xc_domain_getinfo(CTX->xch, domid, 1, &info); if (r < 0) { LOGED(ERROR, domid, "Getting domain info"); rc = ERROR_FAIL; goto out; } max_vcpuid = info.max_vcpu_id; if (scinfo->num_vcpus <= 0) { rc = ERROR_INVAL; goto out; } for (i = 0; i < scinfo->num_vcpus; i++) { if (scinfo->vcpus[i].vcpuid < 0 || scinfo->vcpus[i].vcpuid > max_vcpuid) { LOGD(ERROR, domid, "Invalid VCPU %d: valid range is [0, %d]", scinfo->vcpus[i].vcpuid, max_vcpuid); rc = ERROR_INVAL; goto out; } rc = sched_rtds_validate_params(gc, scinfo->vcpus[i].period, scinfo->vcpus[i].budget); if (rc) { rc = ERROR_INVAL; goto out; } } GCNEW_ARRAY(vcpus, scinfo->num_vcpus); for (i = 0; i < scinfo->num_vcpus; i++) { vcpus[i].vcpuid = scinfo->vcpus[i].vcpuid; vcpus[i].u.rtds.period = scinfo->vcpus[i].period; vcpus[i].u.rtds.budget = scinfo->vcpus[i].budget; } r = xc_sched_rtds_vcpu_set(CTX->xch, domid, vcpus, scinfo->num_vcpus); if (r != 0) { LOGED(ERROR, domid, "Setting vcpu sched rtds"); rc = ERROR_FAIL; goto out; } rc = 0; out: return rc; }
static int libxl__hotplug_nic(libxl__gc *gc, libxl__device *dev, char ***args, char ***env, libxl__device_action action, int num_exec) { char *be_path = libxl__device_backend_path(gc, dev); char *script; int nr = 0, rc = 0; libxl_nic_type nictype; script = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/%s", be_path, "script")); if (!script) { LOGE(ERROR, "unable to read script from %s", be_path); rc = ERROR_FAIL; goto out; } rc = libxl__nic_type(gc, dev, &nictype); if (rc) { LOG(ERROR, "error when fetching nic type"); rc = ERROR_FAIL; goto out; } if (nictype == LIBXL_NIC_TYPE_VIF && num_exec != 0) { rc = 0; goto out; } *env = get_hotplug_env(gc, script, dev); if (!env) { rc = ERROR_FAIL; goto out; } const int arraysize = 4; GCNEW_ARRAY(*args, arraysize); (*args)[nr++] = script; if (nictype == LIBXL_NIC_TYPE_VIF_IOEMU && num_exec) { (*args)[nr++] = action == DEVICE_CONNECT ? "add" : "remove"; (*args)[nr++] = "type_if=tap"; (*args)[nr++] = NULL; } else { (*args)[nr++] = action == DEVICE_CONNECT ? "online" : "offline"; (*args)[nr++] = "type_if=vif"; (*args)[nr++] = NULL; } assert(nr == arraysize); rc = 1; out: return rc; }
static void match_async_exec(libxl__egc *egc, libxl__remus_device *dev) { int arraysize, nr = 0, rc; const libxl_device_disk *disk = dev->backend_dev; libxl__async_exec_state *aes = &dev->aodev.aes; STATE_AO_GC(dev->rds->ao); /* setup env & args */ arraysize = 1; GCNEW_ARRAY(aes->env, arraysize); aes->env[nr++] = NULL; assert(nr <= arraysize); arraysize = 3; nr = 0; GCNEW_ARRAY(aes->args, arraysize); aes->args[nr++] = dev->rds->drbd_probe_script; aes->args[nr++] = disk->pdev_path; aes->args[nr++] = NULL; assert(nr <= arraysize); aes->ao = dev->rds->ao; aes->what = GCSPRINTF("%s %s", aes->args[0], aes->args[1]); aes->timeout_ms = LIBXL_HOTPLUG_TIMEOUT * 1000; aes->callback = match_async_exec_cb; aes->stdfds[0] = -1; aes->stdfds[1] = -1; aes->stdfds[2] = -1; rc = libxl__async_exec_start(gc, aes); if (rc) goto out; return; out: dev->aodev.rc = rc; dev->aodev.callback(egc, &dev->aodev); }
/* Get the RTDS scheduling parameters of vcpu(s) */ static int sched_rtds_vcpu_get(libxl__gc *gc, uint32_t domid, libxl_vcpu_sched_params *scinfo) { uint32_t num_vcpus; int i, r, rc; xc_dominfo_t info; struct xen_domctl_schedparam_vcpu *vcpus; r = xc_domain_getinfo(CTX->xch, domid, 1, &info); if (r < 0) { LOGED(ERROR, domid, "Getting domain info"); rc = ERROR_FAIL; goto out; } if (scinfo->num_vcpus <= 0) { rc = ERROR_INVAL; goto out; } else { num_vcpus = scinfo->num_vcpus; GCNEW_ARRAY(vcpus, num_vcpus); for (i = 0; i < num_vcpus; i++) { if (scinfo->vcpus[i].vcpuid < 0 || scinfo->vcpus[i].vcpuid > info.max_vcpu_id) { LOGD(ERROR, domid, "VCPU index is out of range, " "valid values are within range from 0 to %d", info.max_vcpu_id); rc = ERROR_INVAL; goto out; } vcpus[i].vcpuid = scinfo->vcpus[i].vcpuid; } } r = xc_sched_rtds_vcpu_get(CTX->xch, domid, vcpus, num_vcpus); if (r != 0) { LOGED(ERROR, domid, "Getting vcpu sched rtds"); rc = ERROR_FAIL; goto out; } scinfo->sched = LIBXL_SCHEDULER_RTDS; for (i = 0; i < num_vcpus; i++) { scinfo->vcpus[i].period = vcpus[i].u.rtds.period; scinfo->vcpus[i].budget = vcpus[i].u.rtds.budget; scinfo->vcpus[i].vcpuid = vcpus[i].vcpuid; } rc = 0; out: return rc; }
/* Set the RTDS scheduling parameters of all vcpus of a domain */ static int sched_rtds_vcpu_set_all(libxl__gc *gc, uint32_t domid, const libxl_vcpu_sched_params *scinfo) { int r, rc; int i; uint16_t max_vcpuid; xc_dominfo_t info; struct xen_domctl_schedparam_vcpu *vcpus; uint32_t num_vcpus; r = xc_domain_getinfo(CTX->xch, domid, 1, &info); if (r < 0) { LOGED(ERROR, domid, "Getting domain info"); rc = ERROR_FAIL; goto out; } max_vcpuid = info.max_vcpu_id; if (scinfo->num_vcpus != 1) { rc = ERROR_INVAL; goto out; } if (sched_rtds_validate_params(gc, scinfo->vcpus[0].period, scinfo->vcpus[0].budget)) { rc = ERROR_INVAL; goto out; } num_vcpus = max_vcpuid + 1; GCNEW_ARRAY(vcpus, num_vcpus); for (i = 0; i < num_vcpus; i++) { vcpus[i].vcpuid = i; vcpus[i].u.rtds.period = scinfo->vcpus[0].period; vcpus[i].u.rtds.budget = scinfo->vcpus[0].budget; } r = xc_sched_rtds_vcpu_set(CTX->xch, domid, vcpus, num_vcpus); if (r != 0) { LOGED(ERROR, domid, "Setting vcpu sched rtds"); rc = ERROR_FAIL; goto out; } rc = 0; out: return rc; }
/* Get the RTDS scheduling parameters of all vcpus of a domain */ static int sched_rtds_vcpu_get_all(libxl__gc *gc, uint32_t domid, libxl_vcpu_sched_params *scinfo) { uint32_t num_vcpus; int i, r, rc; xc_dominfo_t info; struct xen_domctl_schedparam_vcpu *vcpus; r = xc_domain_getinfo(CTX->xch, domid, 1, &info); if (r < 0) { LOGED(ERROR, domid, "Getting domain info"); rc = ERROR_FAIL; goto out; } if (scinfo->num_vcpus > 0) { rc = ERROR_INVAL; goto out; } else { num_vcpus = info.max_vcpu_id + 1; GCNEW_ARRAY(vcpus, num_vcpus); for (i = 0; i < num_vcpus; i++) vcpus[i].vcpuid = i; } r = xc_sched_rtds_vcpu_get(CTX->xch, domid, vcpus, num_vcpus); if (r != 0) { LOGED(ERROR, domid, "Getting vcpu sched rtds"); rc = ERROR_FAIL; goto out; } scinfo->sched = LIBXL_SCHEDULER_RTDS; scinfo->num_vcpus = num_vcpus; scinfo->vcpus = libxl__calloc(NOGC, num_vcpus, sizeof(libxl_sched_params)); for (i = 0; i < num_vcpus; i++) { scinfo->vcpus[i].period = vcpus[i].u.rtds.period; scinfo->vcpus[i].budget = vcpus[i].u.rtds.budget; scinfo->vcpus[i].vcpuid = vcpus[i].vcpuid; } rc = 0; out: return rc; }
static void libxl__dm_vifs_from_hvm_guest_config(libxl__gc *gc, libxl_domain_config * const guest_config, libxl_domain_config *dm_config) { int i, nr = guest_config->num_nics; GCNEW_ARRAY(dm_config->nics, nr); for (i=0; i<nr; i++) { dm_config->nics[i] = guest_config->nics[i]; dm_config->nics[i].nictype = LIBXL_NIC_TYPE_VIF; if (dm_config->nics[i].ifname) dm_config->nics[i].ifname = GCSPRINTF("%s" TAP_DEVICE_SUFFIX, dm_config->nics[i].ifname); } dm_config->num_nics = nr; }
void libxl__remus_devices_setup(libxl__egc *egc, libxl__remus_devices_state *rds) { int i, rc; STATE_AO_GC(rds->ao); rc = init_device_subkind(rds); if (rc) goto out; rds->num_devices = 0; rds->num_nics = 0; rds->num_disks = 0; if (rds->device_kind_flags & (1 << LIBXL__DEVICE_KIND_VIF)) rds->nics = libxl_device_nic_list(CTX, rds->domid, &rds->num_nics); if (rds->device_kind_flags & (1 << LIBXL__DEVICE_KIND_VBD)) rds->disks = libxl_device_disk_list(CTX, rds->domid, &rds->num_disks); if (rds->num_nics == 0 && rds->num_disks == 0) goto out; GCNEW_ARRAY(rds->devs, rds->num_nics + rds->num_disks); for (i = 0; i < rds->num_nics; i++) { rds->devs[rds->num_devices++] = remus_device_init(egc, rds, LIBXL__DEVICE_KIND_VIF, &rds->nics[i]); } for (i = 0; i < rds->num_disks; i++) { rds->devs[rds->num_devices++] = remus_device_init(egc, rds, LIBXL__DEVICE_KIND_VBD, &rds->disks[i]); } remus_devices_setup(egc, rds); return; out: rds->callback(egc, rds, rc); }
void libxl__checkpoint_devices_setup(libxl__egc *egc, libxl__checkpoint_devices_state *cds) { int i; STATE_AO_GC(cds->ao); cds->num_devices = 0; cds->num_nics = 0; cds->num_disks = 0; if (cds->device_kind_flags & (1 << LIBXL__DEVICE_KIND_VIF)) cds->nics = libxl_device_nic_list(CTX, cds->domid, &cds->num_nics); if (cds->device_kind_flags & (1 << LIBXL__DEVICE_KIND_VBD)) cds->disks = libxl_device_disk_list(CTX, cds->domid, &cds->num_disks); if (cds->num_nics == 0 && cds->num_disks == 0) goto out; GCNEW_ARRAY(cds->devs, cds->num_nics + cds->num_disks); for (i = 0; i < cds->num_nics; i++) { cds->devs[cds->num_devices++] = checkpoint_device_init(egc, cds, LIBXL__DEVICE_KIND_VIF, &cds->nics[i]); } for (i = 0; i < cds->num_disks; i++) { cds->devs[cds->num_devices++] = checkpoint_device_init(egc, cds, LIBXL__DEVICE_KIND_VBD, &cds->disks[i]); } checkpoint_devices_setup(egc, cds); return; out: cds->callback(egc, cds, 0); }
static void make_bootloader_args(libxl__gc *gc, libxl__bootloader_state *bl, const char *bootloader_path) { const libxl_domain_build_info *info = bl->info; bl->argsspace = 7 + libxl_string_list_length(&info->u.pv.bootloader_args); GCNEW_ARRAY(bl->args, bl->argsspace); #define ARG(arg) bootloader_arg(bl, (arg)) ARG(bootloader_path); if (info->u.pv.kernel) ARG(libxl__sprintf(gc, "--kernel=%s", info->u.pv.kernel)); if (info->u.pv.ramdisk) ARG(libxl__sprintf(gc, "--ramdisk=%s", info->u.pv.ramdisk)); if (info->u.pv.cmdline && *info->u.pv.cmdline != '\0') ARG(libxl__sprintf(gc, "--args=%s", info->u.pv.cmdline)); ARG(libxl__sprintf(gc, "--output=%s", bl->outputpath)); ARG("--output-format=simple0"); ARG(libxl__sprintf(gc, "--output-directory=%s", bl->outputdir)); if (info->u.pv.bootloader_args) { char **p = info->u.pv.bootloader_args; while (*p) { ARG(*p); p++; } } ARG(bl->dls.diskpath); /* Sentinel for execv */ ARG(NULL); #undef ARG }