Beispiel #1
0
static void domcreate_bootloader_done(libxl__egc *egc,
                                      libxl__bootloader_state *bl,
                                      int rc)
{
    libxl__domain_create_state *dcs = CONTAINER_OF(bl, *dcs, bl);
    STATE_AO_GC(bl->ao);

    /* 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;
    const int restore_fd = dcs->restore_fd;
    libxl__domain_build_state *const state = &dcs->build_state;
    libxl__srm_restore_autogen_callbacks *const callbacks =
        &dcs->shs.callbacks.restore.a;

    if (rc) {
        domcreate_rebuild_done(egc, dcs, rc);
        return;
    }

    /* consume bootloader outputs. state->pv_{kernel,ramdisk} have
     * been initialised by the bootloader already.
     */
    state->pv_cmdline = bl->cmdline;

    /* We might be going to call libxl__spawn_local_dm, or _spawn_stub_dm.
     * Fill in any field required by either, including both relevant
     * callbacks (_spawn_stub_dm will overwrite our trespass if needed). */
    dcs->dmss.dm.spawn.ao = ao;
    dcs->dmss.dm.guest_config = dcs->guest_config;
    dcs->dmss.dm.build_state = &dcs->build_state;
    dcs->dmss.dm.callback = domcreate_devmodel_started;
    dcs->dmss.callback = domcreate_devmodel_started;

    if ( restore_fd < 0 ) {
        rc = libxl__domain_build(gc, &d_config->b_info, domid, state);
        domcreate_rebuild_done(egc, dcs, rc);
        return;
    }

    /* Restore */

    rc = libxl__build_pre(gc, domid, info, state);
    if (rc)
        goto out;

    /* read signature */
    int hvm, pae, superpages;
    switch (info->type) {
    case LIBXL_DOMAIN_TYPE_HVM:
        hvm = 1;
        superpages = 1;
        pae = libxl_defbool_val(info->u.hvm.pae);
        callbacks->toolstack_restore = libxl__toolstack_restore;
        break;
    case LIBXL_DOMAIN_TYPE_PV:
        hvm = 0;
        superpages = 0;
        pae = 1;
        break;
    default:
        rc = ERROR_INVAL;
        goto out;
    }
    libxl__xc_domain_restore(egc, dcs,
                             hvm, pae, superpages, 1);
    return;

 out:
    libxl__xc_domain_restore_done(egc, dcs, rc, 0, 0);
}
Beispiel #2
0
/*
 * Returns a boolean indicating whether a further action should be set
 * up by the caller.  This is needed to prevent mutual recursion with
 * stream_continue().
 *
 * It is a bug for this function to ever call stream_continue() or
 * setup_read_record().
 */
static bool process_record(libxl__egc *egc,
                           libxl__stream_read_state *stream)
{
    STATE_AO_GC(stream->ao);
    libxl__domain_create_state *dcs = stream->dcs;
    libxl__sr_record_buf *rec;
    bool further_action_needed = false;
    int rc = 0;

    /* Pop a record from the head of the queue. */
    assert(!LIBXL_STAILQ_EMPTY(&stream->record_queue));
    rec = LIBXL_STAILQ_FIRST(&stream->record_queue);
    LIBXL_STAILQ_REMOVE_HEAD(&stream->record_queue, entry);

    LOG(DEBUG, "Record: %u, length %u", rec->hdr.type, rec->hdr.length);

    switch (rec->hdr.type) {

    case REC_TYPE_END:
        stream_complete(egc, stream, 0);
        break;

    case REC_TYPE_LIBXC_CONTEXT:
        libxl__xc_domain_restore(egc, dcs, &stream->shs, 0, 0, 0);
        break;

    case REC_TYPE_EMULATOR_XENSTORE_DATA:
        if (dcs->guest_config->b_info.device_model_version ==
            LIBXL_DEVICE_MODEL_VERSION_NONE) {
            rc = ERROR_FAIL;
            LOG(ERROR,
                "Received a xenstore emulator record when none was expected");
            goto err;
        }

        if (rec->hdr.length < sizeof(libxl__sr_emulator_hdr)) {
            rc = ERROR_FAIL;
            LOG(ERROR,
                "Emulator xenstore data record too short to contain header");
            goto err;
        }

        rc = libxl__restore_emulator_xenstore_data(dcs,
            rec->body + sizeof(libxl__sr_emulator_hdr),
            rec->hdr.length - sizeof(libxl__sr_emulator_hdr));
        if (rc)
            goto err;

        /*
         * libxl__restore_emulator_xenstore_data() is a synchronous function.
         * Request that our caller queues another action for us.
         */
        further_action_needed = true;
        break;

    case REC_TYPE_EMULATOR_CONTEXT:
        if (dcs->guest_config->b_info.device_model_version ==
            LIBXL_DEVICE_MODEL_VERSION_NONE) {
            rc = ERROR_FAIL;
            LOG(ERROR,
                "Received an emulator context record when none was expected");
            goto err;
        }

        write_emulator_blob(egc, stream, rec);
        break;

    case REC_TYPE_CHECKPOINT_END:
        if (!stream->in_checkpoint) {
            LOG(ERROR, "Unexpected CHECKPOINT_END record in stream");
            rc = ERROR_FAIL;
            goto err;
        }
        checkpoint_done(egc, stream, 0);
        break;

    default:
        LOG(ERROR, "Unrecognised record 0x%08x", rec->hdr.type);
        rc = ERROR_FAIL;
        goto err;
    }

    assert(!rc);
    free_record(rec);
    return further_action_needed;

 err:
    assert(rc);
    free_record(rec);
    stream_complete(egc, stream, rc);
    return false;
}