Exemplo n.º 1
0
/* 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;
}
Exemplo n.º 2
0
static int libxl__append_nic_list(libxl__gc *gc,
                                           uint32_t domid,
                                           libxl_device_nic **nics,
                                           int *nnics)
{
    char *libxl_dir_path = NULL;
    char **dir = NULL;
    unsigned int n = 0;
    libxl_device_nic *pnic = NULL, *pnic_end = NULL;
    int rc;

    libxl_dir_path = GCSPRINTF("%s/device/vif",
                               libxl__xs_libxl_path(gc, domid));
    dir = libxl__xs_directory(gc, XBT_NULL, libxl_dir_path, &n);
    if (dir && n) {
        libxl_device_nic *tmp;
        tmp = realloc(*nics, sizeof (libxl_device_nic) * (*nnics + n));
        if (tmp == NULL)
            return ERROR_NOMEM;
        *nics = tmp;
        pnic = *nics + *nnics;
        pnic_end = *nics + *nnics + n;
        for (; pnic < pnic_end; pnic++, dir++) {
            const char *p;
            p = GCSPRINTF("%s/%s", libxl_dir_path, *dir);
            rc = libxl__device_nic_from_xenstore(gc, p, pnic);
            if (rc) goto out;
        }
        *nnics += n;
    }
    return 0;

 out:
    return rc;
}
Exemplo n.º 3
0
/* out_target_memkb and out_max_memkb can be NULL */
int libxl__get_memory_target(libxl__gc *gc, uint32_t domid,
                             uint64_t *out_target_memkb,
                             uint64_t *out_max_memkb)
{
    int rc;
    char *target = NULL, *static_max = NULL, *endptr = NULL;
    char *dompath = libxl__xs_get_dompath(gc, domid);
    uint64_t target_memkb, max_memkb;

    target = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/memory/target",
                                                    dompath));
    static_max = libxl__xs_read(gc, XBT_NULL,
                    GCSPRINTF("%s/memory/static-max", dompath));

    rc = ERROR_FAIL;
    if ((!target || !static_max) && !domid) {
        rc = libxl__fill_dom0_memory_info(gc, &target_memkb,
                                          &max_memkb);
        if (rc < 0)
            goto out;
    } else if (!target) {
        LOGED(ERROR, domid, "Cannot get target memory info from %s/memory/target",
              dompath);
        goto out;
    } else if (!static_max) {
        LOGED(ERROR, domid,
              "Cannot get target memory info from %s/memory/static-max",
               dompath);
        goto out;
    } else {
        target_memkb = strtoull(target, &endptr, 10);
        if (*endptr != '\0') {
            LOGED(ERROR, domid, "Invalid memory target %s from %s/memory/target\n",
                  target, dompath);
            goto out;
        }
        max_memkb = strtoull(static_max, &endptr, 10);
        if (*endptr != '\0') {
            LOGED(ERROR, domid,
                  "Invalid memory target %s from %s/memory/static-max\n",
                  static_max,
                  dompath);
            goto out;
        }

    }

    if (out_target_memkb)
        *out_target_memkb = target_memkb;

    if (out_max_memkb)
        *out_max_memkb = max_memkb;

    rc = 0;

out:
    return rc;
}
Exemplo n.º 4
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;
}
Exemplo n.º 5
0
const char *libxl__device_nic_devname(libxl__gc *gc,
                                      uint32_t domid,
                                      uint32_t devid,
                                      libxl_nic_type type)
{
    switch (type) {
    case LIBXL_NIC_TYPE_VIF:
        return GCSPRINTF(NETBACK_NIC_NAME, domid, devid);
    case LIBXL_NIC_TYPE_VIF_IOEMU:
        return GCSPRINTF(NETBACK_NIC_NAME TAP_DEVICE_SUFFIX, domid, devid);
    default:
        abort();
    }
}
Exemplo n.º 6
0
int libxl__save_emulator_xenstore_data(libxl__domain_save_state *dss,
                                       char **callee_buf,
                                       uint32_t *callee_len)
{
    STATE_AO_GC(dss->ao);
    const char *xs_root;
    char **entries, *buf = NULL;
    unsigned int nr_entries, i, j, len = 0;
    int rc;

    const uint32_t domid = dss->domid;
    const uint32_t dm_domid = libxl_get_stubdom_id(CTX, domid);

    xs_root = DEVICE_MODEL_XS_PATH(gc, dm_domid, domid, "");

    entries = libxl__xs_directory(gc, 0, GCSPRINTF("%s/physmap", xs_root),
                                  &nr_entries);
    if (!entries || nr_entries == 0) { rc = 0; goto out; }

    for (i = 0; i < nr_entries; ++i) {
        static const char *const physmap_subkeys[] = {
            "start_addr", "size", "name"
        };

        for (j = 0; j < ARRAY_SIZE(physmap_subkeys); ++j) {
            const char *key = GCSPRINTF("physmap/%s/%s",
                                        entries[i], physmap_subkeys[j]);

            const char *val =
                libxl__xs_read(gc, XBT_NULL,
                               GCSPRINTF("%s/%s", xs_root, key));

            if (!val) { rc = ERROR_FAIL; goto out; }

            append_string(gc, &buf, &len, key);
            append_string(gc, &buf, &len, val);
        }
    }

    rc = 0;

 out:
    if (!rc) {
        *callee_buf = buf;
        *callee_len = len;
    }

    return rc;
}
Exemplo n.º 7
0
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;
}
Exemplo n.º 8
0
static void helper_exited(libxl__egc *egc, libxl__ev_child *ch,
                          pid_t pid, int status)
{
    libxl__save_helper_state *shs = CONTAINER_OF(ch, *shs, child);
    STATE_AO_GC(shs->ao);

    /* Convenience aliases */
    const uint32_t domid = shs->domid;

    const char *what =
        GCSPRINTF("domain %"PRIu32" save/restore helper", domid);

    if (status) {
        libxl_report_child_exitstatus(CTX, XTL_ERROR, what, pid, status);
        shs->rc = ERROR_FAIL;
    }

    if (shs->need_results) {
        if (!shs->rc)
            LOG(ERROR,"%s exited without providing results",what);
        shs->rc = ERROR_FAIL;
    }

    if (!shs->completed) {
        if (!shs->rc)
            LOG(ERROR,"%s exited without signaling completion",what);
        shs->rc = ERROR_FAIL;
    }

    helper_done(egc, shs);
    return;
}
Exemplo n.º 9
0
int init_subkind_drbd_disk(libxl__remus_devices_state *rds)
{
    STATE_AO_GC(rds->ao);

    rds->drbd_probe_script = GCSPRINTF("%s/block-drbd-probe",
                                       libxl__xen_script_dir_path());

    return 0;
}
Exemplo n.º 10
0
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;
}
Exemplo n.º 11
0
int libxl__restore_emulator_xenstore_data(libxl__domain_create_state *dcs,
                                          const char *ptr, uint32_t size)
{
    STATE_AO_GC(dcs->ao);
    const char *next = ptr, *end = ptr + size, *key, *val;
    int rc;

    const uint32_t domid = dcs->guest_domid;
    const uint32_t dm_domid = libxl_get_stubdom_id(CTX, domid);
    const char *xs_root = DEVICE_MODEL_XS_PATH(gc, dm_domid, domid, "");

    while (next < end) {
        key = next;
        next = next_string(next, end);

        /* Sanitise 'key'. */
        if (!next) {
            rc = ERROR_FAIL;
            LOG(ERROR, "Key in xenstore data not NUL terminated");
            goto out;
        }
        if (key[0] == '\0') {
            rc = ERROR_FAIL;
            LOG(ERROR, "empty key found in xenstore data");
            goto out;
        }
        if (key[0] == '/') {
            rc = ERROR_FAIL;
            LOG(ERROR, "Key in xenstore data not relative");
            goto out;
        }

        val = next;
        next = next_string(next, end);

        /* Sanitise 'val'. */
        if (!next) {
            rc = ERROR_FAIL;
            LOG(ERROR, "Val in xenstore data not NUL terminated");
            goto out;
        }

        libxl__xs_printf(gc, XBT_NULL,
                         GCSPRINTF("%s/%s", xs_root, key),
                         "%s", val);
    }

    rc = 0;

 out:
    return rc;
}
Exemplo n.º 12
0
char *libxl__device_model_xs_path(libxl__gc *gc, uint32_t dm_domid,
                                  uint32_t domid, const char *format,  ...)
{
    char *s, *fmt;
    va_list ap;

    fmt = GCSPRINTF("/local/domain/%u/device-model/%u%s", dm_domid,
                    domid, format);

    va_start(ap, format);
    s = libxl__vsprintf(gc, fmt, ap);
    va_end(ap);

    return s;
}
Exemplo n.º 13
0
int libxl_get_stubdom_id(libxl_ctx *ctx, int guest_domid)
{
    GC_INIT(ctx);
    char * stubdom_id_s;
    int ret;

    stubdom_id_s = libxl__xs_read(gc, XBT_NULL,
                                  GCSPRINTF("%s/image/device-model-domid",
                                  libxl__xs_get_dompath(gc, guest_domid)));
    if (stubdom_id_s)
        ret = atoi(stubdom_id_s);
    else
        ret = 0;
    GC_FREE;
    return ret;
}
Exemplo n.º 14
0
Arquivo: libxl_dm.c Projeto: jsgf/xen
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;
}
Exemplo n.º 15
0
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;
}
Exemplo n.º 16
0
int libxl__device_model_version_running(libxl__gc *gc, uint32_t domid)
{
    char *path = NULL;
    char *dm_version = NULL;
    libxl_device_model_version value;

    path = libxl__xs_libxl_path(gc, domid);
    path = GCSPRINTF("%s/dm-version", path);
    dm_version = libxl__xs_read(gc, XBT_NULL, path);
    if (!dm_version) {
        return LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN_TRADITIONAL;
    }

    if (libxl_device_model_version_from_string(dm_version, &value) < 0) {
        LOGD(ERROR, domid, "fatal: %s contain a wrong value (%s)", path, dm_version);
        return -1;
    }
    return value;
}
Exemplo n.º 17
0
int libxl_is_stubdom(libxl_ctx *ctx, uint32_t domid, uint32_t *target_domid)
{
    GC_INIT(ctx);
    char *target, *endptr;
    uint32_t value;
    int ret = 0;

    target = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/target",
                            libxl__xs_get_dompath(gc, domid)));
    if (!target)
        goto out;
    value = strtol(target, &endptr, 10);
    if (*endptr != '\0')
        goto out;
    if (target_domid)
        *target_domid = value;
    ret = 1;
out:
    GC_FREE;
    return ret;
}
Exemplo n.º 18
0
int libxl_devid_to_device_nic(libxl_ctx *ctx, uint32_t domid,
                              int devid, libxl_device_nic *nic)
{
    GC_INIT(ctx);
    char *libxl_dom_path, *libxl_path;
    int rc = ERROR_FAIL;

    libxl_device_nic_init(nic);
    libxl_dom_path = libxl__xs_libxl_path(gc, domid);
    if (!libxl_dom_path)
        goto out;

    libxl_path = GCSPRINTF("%s/device/vif/%d", libxl_dom_path, devid);

    rc = libxl__device_nic_from_xenstore(gc, libxl_path, nic);
    if (rc) goto out;

    rc = 0;
out:
    GC_FREE;
    return rc;
}
Exemplo n.º 19
0
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);
}
Exemplo n.º 20
0
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;
}
Exemplo n.º 21
0
/*
 * If the device has a vifname, then use that instead of
 * the vifX.Y format.
 * it must ONLY be used for remus because if driver domains
 * were in use it would constitute a security vulnerability.
 */
static const char *get_vifname(libxl__checkpoint_device *dev,
                               const libxl_device_nic *nic)
{
    const char *vifname = NULL;
    const char *path;
    int rc;

    STATE_AO_GC(dev->cds->ao);

    /* Convenience aliases */
    const uint32_t domid = dev->cds->domid;

    path = GCSPRINTF("%s/backend/vif/%d/%d/vifname",
                     libxl__xs_get_dompath(gc, 0), domid, nic->devid);
    rc = libxl__xs_read_checked(gc, XBT_NULL, path, &vifname);
    if (!rc && !vifname) {
        vifname = libxl__device_nic_devname(gc, domid,
                                            nic->devid,
                                            nic->nictype);
    }

    return vifname;
}
Exemplo n.º 22
0
static void bootloader_gotptys(libxl__egc *egc, libxl__openpty_state *op)
{
    libxl__bootloader_state *bl = CONTAINER_OF(op, *bl, openpty);
    STATE_AO_GC(bl->ao);
    int rc, r;
    char *const env[] = { "TERM", "vt100", NULL };

    if (bl->openpty.rc) {
        rc = bl->openpty.rc;
        goto out;
    }

    /*
     * We need to present the bootloader's tty as a pty slave that xenconsole
     * can access.  Since the bootloader itself needs a pty slave,
     * we end up with a connection like this:
     *
     * xenconsole -- (slave pty1 master) <-> (master pty2 slave) -- bootloader
     *
     * where we copy characters between the two master fds, as well as
     * listening on the bootloader's fifo for the results.
     */

    char *dom_console_xs_path;
    char dom_console_slave_tty_path[PATH_MAX];
    rc = setup_xenconsoled_pty(egc, bl,
                               &dom_console_slave_tty_path[0],
                               sizeof(dom_console_slave_tty_path));
    if (rc) goto out;

    char *dompath = libxl__xs_get_dompath(gc, bl->domid);
    if (!dompath) {
        rc = ERROR_FAIL;
        goto out;
    }

    dom_console_xs_path = GCSPRINTF("%s/console/tty", dompath);

    rc = libxl__xs_write(gc, XBT_NULL, dom_console_xs_path, "%s",
                         dom_console_slave_tty_path);
    if (rc) {
        LOGE(ERROR,"xs write console path %s := %s failed",
             dom_console_xs_path, dom_console_slave_tty_path);
        rc = ERROR_FAIL;
        goto out;
    }

    bl->deathcheck.what = "stopping bootloader";
    bl->deathcheck.domid = bl->domid;
    bl->deathcheck.callback = bootloader_domaindeath;
    rc = libxl__domaindeathcheck_start(gc, &bl->deathcheck);
    if (rc) goto out;

    if (bl->console_available)
        bl->console_available(egc, bl);

    int bootloader_master = libxl__carefd_fd(bl->ptys[0].master);
    int xenconsole_master = libxl__carefd_fd(bl->ptys[1].master);

    libxl_fd_set_nonblock(CTX, bootloader_master, 1);
    libxl_fd_set_nonblock(CTX, xenconsole_master, 1);

    bl->keystrokes.writefd   = bl->display.readfd   = bootloader_master;
    bl->keystrokes.writewhat = bl->display.readwhat = "bootloader pty";

    bl->keystrokes.readfd   = bl->display.writefd   = xenconsole_master;
    bl->keystrokes.readwhat = bl->display.writewhat = "xenconsole client pty";

    bl->keystrokes.ao = ao;
    bl->keystrokes.maxsz = BOOTLOADER_BUF_OUT;
    bl->keystrokes.copywhat =
        GCSPRINTF("bootloader input for domain %"PRIu32, bl->domid);
    bl->keystrokes.callback =         bootloader_keystrokes_copyfail;
    bl->keystrokes.callback_pollhup = bootloader_keystrokes_copyfail;
    /* pollhup gets called with errnoval==-1 which is not otherwise
     * possible since errnos are nonnegative, so it's unambiguous */
    rc = libxl__datacopier_start(&bl->keystrokes);
    if (rc) goto out;

    bl->display.ao = ao;
    bl->display.maxsz = BOOTLOADER_BUF_IN;
    bl->display.copywhat =
        GCSPRINTF("bootloader output for domain %"PRIu32, bl->domid);
    bl->display.callback =         bootloader_display_copyfail;
    bl->display.callback_pollhup = bootloader_display_copyfail;
    rc = libxl__datacopier_start(&bl->display);
    if (rc) goto out;

    LOG(DEBUG, "executing bootloader: %s", bl->args[0]);
    for (const char **blarg = bl->args;
            *blarg;
            blarg++)
        LOG(DEBUG, "  bootloader arg: %s", *blarg);

    struct termios termattr;

    pid_t pid = libxl__ev_child_fork(gc, &bl->child, bootloader_finished);
    if (pid == -1) {
        rc = ERROR_FAIL;
        goto out;
    }

    if (!pid) {
        /* child */
        r = login_tty(libxl__carefd_fd(bl->ptys[0].slave));
        if (r) {
            LOGE(ERROR, "login_tty failed");
            exit(-1);
        }
        libxl__exec(gc, -1, -1, -1, bl->args[0], (char **) bl->args, env);
        exit(-1);
    }

    /* parent */

    /*
     * On Solaris, the master pty side does not have terminal semantics,
     * so don't try to set any attributes, as it will fail.
     */
#if !defined(__sun__)
    tcgetattr(bootloader_master, &termattr);
    cfmakeraw(&termattr);
    tcsetattr(bootloader_master, TCSANOW, &termattr);
#endif

    return;

out:
    bootloader_callback(egc, bl, rc);
}
Exemplo n.º 23
0
void libxl__bootloader_run(libxl__egc *egc, libxl__bootloader_state *bl)
{
    STATE_AO_GC(bl->ao);
    const libxl_domain_build_info *info = bl->info;
    uint32_t domid = bl->domid;
    char *logfile_tmp = NULL;
    int rc, r;

    libxl__bootloader_init(bl);

    if (info->type != LIBXL_DOMAIN_TYPE_PV) {
        LOG(DEBUG, "not a PV domain, skipping bootloader");
        rc = 0;
        goto out_ok;
    }

    if (!info->u.pv.bootloader) {
        LOG(DEBUG, "no bootloader configured, using user supplied kernel");
        bl->kernel->path = bl->info->u.pv.kernel;
        bl->ramdisk->path = bl->info->u.pv.ramdisk;
        bl->cmdline = bl->info->u.pv.cmdline;
        rc = 0;
        goto out_ok;
    }

    if (!bl->disk) {
        LOG(ERROR, "cannot run bootloader with no boot disk");
        rc = ERROR_FAIL;
        goto out;
    }

    bootloader_setpaths(gc, bl);

    const char *logfile_leaf = GCSPRINTF("bootloader.%"PRIu32, domid);
    rc = libxl_create_logfile(CTX, logfile_leaf, &logfile_tmp);
    if (rc) goto out;

    /* Transfer ownership of log filename to bl and the gc */
    bl->logfile = logfile_tmp;
    libxl__ptr_add(gc, logfile_tmp);
    logfile_tmp = NULL;

    bl->display.log = fopen(bl->logfile, "a");
    if (!bl->display.log) {
        LOGE(ERROR, "failed to create bootloader logfile %s", bl->logfile);
        rc = ERROR_FAIL;
        goto out;
    }

    for (;;) {
        r = mkdir(bl->outputdir, 0600);
        if (!r) break;
        if (errno == EINTR) continue;
        if (errno == EEXIST) break;
        LOGE(ERROR, "failed to create bootloader dir %s", bl->outputdir);
        rc = ERROR_FAIL;
        goto out;
    }

    for (;;) {
        r = open(bl->outputpath, O_WRONLY|O_CREAT|O_TRUNC, 0600);
        if (r>=0) {
            close(r);
            break;
        }
        if (errno == EINTR) continue;
        LOGE(ERROR, "failed to precreate bootloader output %s", bl->outputpath);
        rc = ERROR_FAIL;
        goto out;
    }


    /* This sets the state of the dls struct from Undefined to Idle */
    libxl__device_disk_local_init(&bl->dls);
    bl->dls.ao = ao;
    bl->dls.in_disk = bl->disk;
    bl->dls.blkdev_start = info->blkdev_start;
    bl->dls.callback = bootloader_disk_attached_cb;
    libxl__device_disk_local_initiate_attach(egc, &bl->dls);
    return;

out:
    assert(rc);
out_ok:
    free(logfile_tmp);
    bootloader_callback(egc, bl, rc);
}
Exemplo n.º 24
0
static void bootloader_setpaths(libxl__gc *gc, libxl__bootloader_state *bl)
{
    uint32_t domid = bl->domid;
    bl->outputdir = GCSPRINTF(XEN_RUN_DIR "/bootloader.%"PRIu32".d", domid);
    bl->outputpath = GCSPRINTF(XEN_RUN_DIR "/bootloader.%"PRIu32".out", domid);
}
Exemplo n.º 25
0
Arquivo: libxl_dm.c Projeto: jsgf/xen
void libxl__spawn_local_dm(libxl__egc *egc, libxl__dm_spawn_state *dmss)
{
    /* convenience aliases */
    const int domid = dmss->guest_domid;
    libxl__domain_build_state *const state = dmss->build_state;
    libxl__spawn_state *const spawn = &dmss->spawn;

    STATE_AO_GC(dmss->spawn.ao);

    libxl_ctx *ctx = CTX;
    libxl_domain_config *guest_config = dmss->guest_config;
    const libxl_domain_create_info *c_info = &guest_config->c_info;
    const libxl_domain_build_info *b_info = &guest_config->b_info;
    const libxl_vnc_info *vnc = libxl__dm_vnc(guest_config);
    char *path, *logfile;
    int logfile_w, null;
    int rc;
    char **args, **arg;
    xs_transaction_t t;
    char *vm_path;
    char **pass_stuff;
    const char *dm;

    if (libxl_defbool_val(b_info->device_model_stubdomain)) {
        abort();
    }

    dm = libxl__domain_device_model(gc, b_info);
    if (!dm) {
        rc = ERROR_FAIL;
        goto out;
    }
    if (access(dm, X_OK) < 0) {
        LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR,
                         "device model %s is not executable", dm);
        rc = ERROR_FAIL;
        goto out;
    }
    args = libxl__build_device_model_args(gc, dm, domid, guest_config, state);
    if (!args) {
        rc = ERROR_FAIL;
        goto out;
    }

    if (b_info->type == LIBXL_DOMAIN_TYPE_HVM) {
        path = xs_get_domain_path(ctx->xsh, domid);
        libxl__xs_write(gc, XBT_NULL,
                        libxl__sprintf(gc, "%s/hvmloader/bios", path),
                        "%s", libxl_bios_type_to_string(b_info->u.hvm.bios));
        /* Disable relocating memory to make the MMIO hole larger
         * unless we're running qemu-traditional */
        libxl__xs_write(gc, XBT_NULL,
                        libxl__sprintf(gc,
                                       "%s/hvmloader/allow-memory-relocate",
                                       path),
                        "%d",
                        b_info->device_model_version==LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN_TRADITIONAL);
        free(path);
    }

    path = libxl__sprintf(gc, "/local/domain/0/device-model/%d", domid);
    xs_mkdir(ctx->xsh, XBT_NULL, path);

    if (b_info->type == LIBXL_DOMAIN_TYPE_HVM &&
        b_info->device_model_version
        == LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN_TRADITIONAL)
        libxl__xs_write(gc, XBT_NULL, libxl__sprintf(gc, "%s/disable_pf", path),
                    "%d", !libxl_defbool_val(b_info->u.hvm.xen_platform_pci));

    libxl_create_logfile(ctx,
                         libxl__sprintf(gc, "qemu-dm-%s", c_info->name),
                         &logfile);
    logfile_w = open(logfile, O_WRONLY|O_CREAT|O_APPEND, 0644);
    free(logfile);
    null = open("/dev/null", O_RDONLY);

    const char *dom_path = libxl__xs_get_dompath(gc, domid);
    spawn->pidpath = GCSPRINTF("%s/%s", dom_path, "image/device-model-pid");

    if (vnc && vnc->passwd) {
        /* This xenstore key will only be used by qemu-xen-traditionnal.
         * The code to supply vncpasswd to qemu-xen is later. */
retry_transaction:
        /* Find uuid and the write the vnc password to xenstore for qemu. */
        t = xs_transaction_start(ctx->xsh);
        vm_path = libxl__xs_read(gc,t,libxl__sprintf(gc, "%s/vm", dom_path));
        if (vm_path) {
            /* Now write the vncpassword into it. */
            pass_stuff = libxl__calloc(gc, 3, sizeof(char *));
            pass_stuff[0] = "vncpasswd";
            pass_stuff[1] = vnc->passwd;
            libxl__xs_writev(gc,t,vm_path,pass_stuff);
            if (!xs_transaction_end(ctx->xsh, t, 0))
                if (errno == EAGAIN)
                    goto retry_transaction;
        }
    }

    LIBXL__LOG(CTX, XTL_DEBUG, "Spawning device-model %s with arguments:", dm);
    for (arg = args; *arg; arg++)
        LIBXL__LOG(CTX, XTL_DEBUG, "  %s", *arg);

    spawn->what = GCSPRINTF("domain %d device model", domid);
    spawn->xspath = GCSPRINTF("/local/domain/0/device-model/%d/state", domid);
    spawn->timeout_ms = LIBXL_DEVICE_MODEL_START_TIMEOUT * 1000;
    spawn->pidpath = GCSPRINTF("%s/image/device-model-pid", dom_path);
    spawn->midproc_cb = libxl__spawn_record_pid;
    spawn->confirm_cb = device_model_confirm;
    spawn->failure_cb = device_model_startup_failed;
    spawn->detached_cb = device_model_detached;

    rc = libxl__spawn_spawn(egc, spawn);
    if (rc < 0)
        goto out_close;
    if (!rc) { /* inner child */
        setsid();
        libxl__exec(gc, null, logfile_w, logfile_w, dm, args, NULL);
    }

    rc = 0;

out_close:
    close(null);
    close(logfile_w);
out:
    if (rc)
        device_model_spawn_outcome(egc, dmss, rc);
}
Exemplo n.º 26
0
static void run_helper(libxl__egc *egc, libxl__save_helper_state *shs,
                       const char *mode_arg, int stream_fd,
                       const int *preserve_fds, int num_preserve_fds,
                       const unsigned long *argnums, int num_argnums)
{
    STATE_AO_GC(shs->ao);
    const char *args[4 + num_argnums];
    const char **arg = args;
    int i, rc;

    /* Resources we must free */
    libxl__carefd *childs_pipes[2] = { 0,0 };

    /* Convenience aliases */
    const uint32_t domid = shs->domid;

    shs->rc = 0;
    shs->completed = 0;
    shs->pipes[0] = shs->pipes[1] = 0;
    libxl__ev_fd_init(&shs->readable);
    libxl__ev_child_init(&shs->child);

    shs->stdin_what = GCSPRINTF("domain %"PRIu32" save/restore helper"
                                " stdin pipe", domid);
    shs->stdout_what = GCSPRINTF("domain %"PRIu32" save/restore helper"
                                 " stdout pipe", domid);

    *arg++ = getenv("LIBXL_SAVE_HELPER") ?: PRIVATE_BINDIR "/" "libxl-save-helper";
    *arg++ = mode_arg;
    const char **stream_fd_arg = arg++;
    for (i=0; i<num_argnums; i++)
        *arg++ = GCSPRINTF("%lu", argnums[i]);
    *arg++ = 0;
    assert(arg == args + ARRAY_SIZE(args));

    libxl__carefd_begin();
    int childfd;
    for (childfd=0; childfd<2; childfd++) {
        /* Setting up the pipe for the child's fd childfd */
        int fds[2];
        if (libxl_pipe(CTX,fds)) {
            rc = ERROR_FAIL;
            libxl__carefd_unlock();
            goto out;
        }
        int childs_end = childfd==0 ? 0 /*read*/  : 1 /*write*/;
        int our_end    = childfd==0 ? 1 /*write*/ : 0 /*read*/;
        childs_pipes[childfd] = libxl__carefd_record(CTX, fds[childs_end]);
        shs->pipes[childfd] =   libxl__carefd_record(CTX, fds[our_end]);
    }
    libxl__carefd_unlock();

    pid_t pid = libxl__ev_child_fork(gc, &shs->child, helper_exited);
    if (!pid) {
        if (stream_fd <= 2) {
            stream_fd = dup(stream_fd);
            if (stream_fd < 0) {
                LOGE(ERROR,"dup migration stream fd");
                exit(-1);
            }
        }
        libxl_fd_set_cloexec(CTX, stream_fd, 0);
        *stream_fd_arg = GCSPRINTF("%d", stream_fd);

        for (i=0; i<num_preserve_fds; i++)
            if (preserve_fds[i] >= 0) {
                assert(preserve_fds[i] > 2);
                libxl_fd_set_cloexec(CTX, preserve_fds[i], 0);
            }

        libxl__exec(gc,
                    libxl__carefd_fd(childs_pipes[0]),
                    libxl__carefd_fd(childs_pipes[1]),
                    -1,
                    args[0], (char**)args, 0);
    }

    libxl__carefd_close(childs_pipes[0]);
    libxl__carefd_close(childs_pipes[1]);

    rc = libxl__ev_fd_register(gc, &shs->readable, helper_stdout_readable,
                               libxl__carefd_fd(shs->pipes[1]), POLLIN|POLLPRI);
    if (rc) goto out;
    return;

 out:
    libxl__carefd_close(childs_pipes[0]);
    libxl__carefd_close(childs_pipes[1]);
    helper_failed(egc, shs, rc);;
}
Exemplo n.º 27
0
int libxl__domain_rename(libxl__gc *gc, uint32_t domid,
                         const char *old_name, const char *new_name,
                         xs_transaction_t trans)
{
    libxl_ctx *ctx = libxl__gc_owner(gc);
    char *dom_path = 0;
    const char *name_path;
    char *got_old_name;
    unsigned int got_old_len;
    xs_transaction_t our_trans = 0;
    uint32_t stub_dm_domid;
    const char *stub_dm_old_name = NULL, *stub_dm_new_name = NULL;
    int rc;
    libxl_dominfo info;
    char *uuid;
    const char *vm_name_path;

    libxl_dominfo_init(&info);

    dom_path = libxl__xs_get_dompath(gc, domid);
    if (!dom_path) goto x_nomem;

    name_path= GCSPRINTF("%s/name", dom_path);
    if (!name_path) goto x_nomem;

    stub_dm_domid = libxl_get_stubdom_id(CTX, domid);
    if (stub_dm_domid) {
        stub_dm_old_name = libxl__stub_dm_name(gc, old_name);
        stub_dm_new_name = libxl__stub_dm_name(gc, new_name);
    }

 retry_transaction:
    if (!trans) {
        trans = our_trans = xs_transaction_start(ctx->xsh);
        if (!our_trans) {
            LOGEVD(ERROR, errno, domid, "Create xs transaction for domain (re)name");
            goto x_fail;
        }
    }

    if (!new_name) {
        LOGD(ERROR, domid, "New domain name not specified");
        rc = ERROR_INVAL;
        goto x_rc;
    }

    if (new_name[0]) {
        /* nonempty names must be unique */
        uint32_t domid_e;
        rc = libxl_name_to_domid(ctx, new_name, &domid_e);
        if (rc == ERROR_INVAL) {
            /* no such domain, good */
        } else if (rc != 0) {
            LOGD(ERROR, domid, "Unexpected error checking for existing domain");
            goto x_rc;
        } else if (domid_e == domid) {
            /* domain already has this name, ok (but we do still
             * need the rest of the code as we may need to check
             * old_name, for example). */
        } else {
            LOGD(ERROR, domid, "Domain with name \"%s\" already exists.", new_name);
            rc = ERROR_INVAL;
            goto x_rc;
        }
    }

    if (old_name) {
        got_old_name = xs_read(ctx->xsh, trans, name_path, &got_old_len);
        if (!got_old_name) {
            LOGEVD(ERROR, errno, domid,
                   "Check old name for domain allegedly named `%s'",
                   old_name);
            goto x_fail;
        }
        if (strcmp(old_name, got_old_name)) {
            LOGD(ERROR, domid,
                 "Allegedly named `%s' is actually named `%s' - racing ?",
                 old_name,
                 got_old_name);
            free(got_old_name);
            goto x_fail;
        }
        free(got_old_name);
    }
    if (!xs_write(ctx->xsh, trans, name_path,
                  new_name, strlen(new_name))) {
        LOGD(ERROR, domid,
             "Failed to write new name `%s'"
             " for domain previously named `%s'",
             new_name,
             old_name);
        goto x_fail;
    }

    /* update /vm/<uuid>/name */
    rc = libxl_domain_info(ctx, &info, domid);
    if (rc)
        goto x_rc;

    uuid = GCSPRINTF(LIBXL_UUID_FMT, LIBXL_UUID_BYTES(info.uuid));
    vm_name_path = GCSPRINTF("/vm/%s/name", uuid);
    if (libxl__xs_write_checked(gc, trans, vm_name_path, new_name))
        goto x_fail;

    if (stub_dm_domid) {
        rc = libxl__domain_rename(gc, stub_dm_domid,
                                  stub_dm_old_name,
                                  stub_dm_new_name,
                                  trans);
        if (rc) {
            LOGED(ERROR, domid, "Unable to rename stub-domain");
            goto x_rc;
        }
    }

    if (our_trans) {
        if (!xs_transaction_end(ctx->xsh, our_trans, 0)) {
            trans = our_trans = 0;
            if (errno != EAGAIN) {
                LOGD(ERROR, domid,
                     "Failed to commit new name `%s'"
                     " for domain previously named `%s'",
                     new_name,
                     old_name);
                goto x_fail;
            }
            LOGD(DEBUG, domid,
                 "Need to retry rename transaction"
                 " for domain (name_path=\"%s\", new_name=\"%s\")",
                 name_path,
                 new_name);
            goto retry_transaction;
        }
        our_trans = 0;
    }

    rc = 0;
 x_rc:
    if (our_trans) xs_transaction_end(ctx->xsh, our_trans, 1);
    libxl_dominfo_dispose(&info);
    return rc;

 x_fail:  rc = ERROR_FAIL;  goto x_rc;
 x_nomem: rc = ERROR_NOMEM; goto x_rc;
}
Exemplo n.º 28
0
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;
}
Exemplo n.º 29
0
void libxl__xc_domain_restore_done(libxl__egc *egc, void *dcs_void,
                                   int ret, int retval, int errnoval)
{
    libxl__domain_create_state *dcs = dcs_void;
    STATE_AO_GC(dcs->ao);
    libxl_ctx *ctx = libxl__gc_owner(gc);
    char **vments = NULL, **localents = NULL;
    struct timeval start_time;
    int i, esave, flags;

    /* convenience aliases */
    const uint32_t domid = dcs->guest_domid;
    libxl_domain_config *const d_config = dcs->guest_config;
    libxl_domain_build_info *const info = &d_config->b_info;
    libxl__domain_build_state *const state = &dcs->build_state;
    const int fd = dcs->restore_fd;

    if (ret)
        goto out;

    if (retval) {
        LOGEV(ERROR, errnoval, "restoring domain");
        ret = ERROR_FAIL;
        goto out;
    }

    gettimeofday(&start_time, NULL);

    switch (info->type) {
    case LIBXL_DOMAIN_TYPE_HVM:
        vments = libxl__calloc(gc, 7, sizeof(char *));
        vments[0] = "rtc/timeoffset";
        vments[1] = (info->u.hvm.timeoffset) ? info->u.hvm.timeoffset : "";
        vments[2] = "image/ostype";
        vments[3] = "hvm";
        vments[4] = "start_time";
        vments[5] = libxl__sprintf(gc, "%lu.%02d", start_time.tv_sec,(int)start_time.tv_usec/10000);
        break;
    case LIBXL_DOMAIN_TYPE_PV:
        vments = libxl__calloc(gc, 11, sizeof(char *));
        i = 0;
        vments[i++] = "image/ostype";
        vments[i++] = "linux";
        vments[i++] = "image/kernel";
        vments[i++] = (char *) state->pv_kernel.path;
        vments[i++] = "start_time";
        vments[i++] = libxl__sprintf(gc, "%lu.%02d", start_time.tv_sec,(int)start_time.tv_usec/10000);
        if (state->pv_ramdisk.path) {
            vments[i++] = "image/ramdisk";
            vments[i++] = (char *) state->pv_ramdisk.path;
        }
        if (state->pv_cmdline) {
            vments[i++] = "image/cmdline";
            vments[i++] = (char *) state->pv_cmdline;
        }
        break;
    default:
        ret = ERROR_INVAL;
        goto out;
    }
    ret = libxl__build_post(gc, domid, info, state, vments, localents);
    if (ret)
        goto out;

    if (info->type == LIBXL_DOMAIN_TYPE_HVM) {
        state->saved_state = GCSPRINTF(
                       XC_DEVICE_MODEL_RESTORE_FILE".%d", domid);
    }

out:
    if (info->type == LIBXL_DOMAIN_TYPE_PV) {
        libxl__file_reference_unmap(&state->pv_kernel);
        libxl__file_reference_unmap(&state->pv_ramdisk);
    }

    esave = errno;

    flags = fcntl(fd, F_GETFL);
    if (flags == -1) {
        LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "unable to get flags on restore fd");
    } else {
        flags &= ~O_NONBLOCK;
        if (fcntl(fd, F_SETFL, flags) == -1)
            LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "unable to put restore fd"
                         " back to blocking mode");
    }

    errno = esave;
    domcreate_rebuild_done(egc, dcs, ret);
}
Exemplo n.º 30
0
/*
 * In return, the script writes the name of REMUS_IFB device (during setup)
 * to be used for output buffering into XENBUS_PATH/ifb
 */
static void netbuf_setup_script_cb(libxl__egc *egc,
                                   libxl__async_exec_state *aes,
                                   int rc, int status)
{
    libxl__ao_device *aodev = CONTAINER_OF(aes, *aodev, aes);
    libxl__checkpoint_device *dev = CONTAINER_OF(aodev, *dev, aodev);
    libxl__remus_device_nic *remus_nic = dev->concrete_data;
    libxl__checkpoint_devices_state *cds = dev->cds;
    libxl__remus_state *rs = cds->concrete_data;
    const char *out_path_base, *hotplug_error = NULL;

    STATE_AO_GC(cds->ao);

    /* Convenience aliases */
    const uint32_t domid = cds->domid;
    const int devid = remus_nic->devid;
    const char *const vif = remus_nic->vif;
    const char **const ifb = &remus_nic->ifb;

    if (status && !rc)
        rc = ERROR_FAIL;
    if (rc)
        goto out;

    /*
     * we need to get ifb first because it's needed for teardown
     */
    rc = libxl__xs_read_checked(gc, XBT_NULL,
                                GCSPRINTF("%s/remus/netbuf/%d/ifb",
                                          libxl__xs_libxl_path(gc, domid),
                                          devid),
                                ifb);
    if (rc)
        goto out;

    if (!(*ifb)) {
        LOGD(ERROR, domid, "Cannot get ifb dev name for domain %u dev %s",
             domid, vif);
        rc = ERROR_FAIL;
        goto out;
    }

    out_path_base = GCSPRINTF("%s/remus/netbuf/%d",
                              libxl__xs_libxl_path(gc, domid), devid);

    rc = libxl__xs_read_checked(gc, XBT_NULL,
                                GCSPRINTF("%s/hotplug-error", out_path_base),
                                &hotplug_error);
    if (rc)
        goto out;

    if (hotplug_error) {
        LOGD(ERROR, domid, "netbuf script %s setup failed for vif %s: %s",
             rs->netbufscript, vif, hotplug_error);
        rc = ERROR_FAIL;
        goto out;
    }

    if (status) {
        rc = ERROR_FAIL;
        goto out;
    }

    LOGD(DEBUG, domid, "%s will buffer packets from vif %s", *ifb, vif);
    rc = init_qdisc(cds, remus_nic);

out:
    aodev->rc = rc;
    aodev->callback(egc, aodev);
}