static void curl_readv_bh_cb(void *p)
{
    CURLState *state;

    CURLAIOCB *acb = p;
    BDRVCURLState *s = acb->common.bs->opaque;

    qemu_bh_delete(acb->bh);
    acb->bh = NULL;

    size_t start = acb->sector_num * SECTOR_SIZE;
    size_t end;

    // In case we have the requested data already (e.g. read-ahead),
    // we can just call the callback and be done.
    switch (curl_find_buf(s, start, acb->nb_sectors * SECTOR_SIZE, acb)) {
        case FIND_RET_OK:
            qemu_aio_release(acb);
            // fall through
        case FIND_RET_WAIT:
            return;
        default:
            break;
    }

    // No cache found, so let's start a new request
    state = curl_init_state(s);
    if (!state) {
        acb->common.cb(acb->common.opaque, -EIO);
        qemu_aio_release(acb);
        return;
    }

    acb->start = 0;
    acb->end = (acb->nb_sectors * SECTOR_SIZE);

    state->buf_off = 0;
    if (state->orig_buf)
        g_free(state->orig_buf);
    state->buf_start = start;
    state->buf_len = acb->end + s->readahead_size;
    end = MIN(start + state->buf_len, s->len) - 1;
    state->orig_buf = g_malloc(state->buf_len);
    state->acb[0] = acb;

    snprintf(state->range, 127, "%zd-%zd", start, end);
    DPRINTF("CURL (AIO): Reading %d at %zd (%s)\n",
            (acb->nb_sectors * SECTOR_SIZE), start, state->range);
    curl_easy_setopt(state->curl, CURLOPT_RANGE, state->range);

    curl_multi_add_handle(s->multi, state->curl);
    curl_multi_do(s);

}
Unknown