Revision 363c3c85
b/block/curl.c | ||
---|---|---|
47 | 47 |
|
48 | 48 |
typedef struct CURLAIOCB { |
49 | 49 |
BlockDriverAIOCB common; |
50 |
QEMUBH *bh; |
|
50 | 51 |
QEMUIOVector *qiov; |
52 |
|
|
53 |
int64_t sector_num; |
|
54 |
int nb_sectors; |
|
55 |
|
|
51 | 56 |
size_t start; |
52 | 57 |
size_t end; |
53 | 58 |
} CURLAIOCB; |
... | ... | |
440 | 445 |
.cancel = curl_aio_cancel, |
441 | 446 |
}; |
442 | 447 |
|
443 |
static BlockDriverAIOCB *curl_aio_readv(BlockDriverState *bs, |
|
444 |
int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, |
|
445 |
BlockDriverCompletionFunc *cb, void *opaque) |
|
448 |
|
|
449 |
static void curl_readv_bh_cb(void *p) |
|
446 | 450 |
{ |
447 |
BDRVCURLState *s = bs->opaque; |
|
448 |
CURLAIOCB *acb; |
|
449 |
size_t start = sector_num * SECTOR_SIZE; |
|
450 |
size_t end; |
|
451 | 451 |
CURLState *state; |
452 | 452 |
|
453 |
acb = qemu_aio_get(&curl_aio_pool, bs, cb, opaque); |
|
454 |
if (!acb) |
|
455 |
return NULL; |
|
453 |
CURLAIOCB *acb = p; |
|
454 |
BDRVCURLState *s = acb->common.bs->opaque; |
|
456 | 455 |
|
457 |
acb->qiov = qiov; |
|
456 |
qemu_bh_delete(acb->bh); |
|
457 |
acb->bh = NULL; |
|
458 |
|
|
459 |
size_t start = acb->sector_num * SECTOR_SIZE; |
|
460 |
size_t end; |
|
458 | 461 |
|
459 | 462 |
// In case we have the requested data already (e.g. read-ahead), |
460 | 463 |
// we can just call the callback and be done. |
461 |
|
|
462 |
switch (curl_find_buf(s, start, nb_sectors * SECTOR_SIZE, acb)) { |
|
464 |
switch (curl_find_buf(s, start, acb->nb_sectors * SECTOR_SIZE, acb)) { |
|
463 | 465 |
case FIND_RET_OK: |
464 | 466 |
qemu_aio_release(acb); |
465 | 467 |
// fall through |
466 | 468 |
case FIND_RET_WAIT: |
467 |
return &acb->common;
|
|
469 |
return; |
|
468 | 470 |
default: |
469 | 471 |
break; |
470 | 472 |
} |
471 | 473 |
|
472 | 474 |
// No cache found, so let's start a new request |
473 |
|
|
474 | 475 |
state = curl_init_state(s); |
475 |
if (!state) |
|
476 |
return NULL; |
|
476 |
if (!state) { |
|
477 |
acb->common.cb(acb->common.opaque, -EIO); |
|
478 |
qemu_aio_release(acb); |
|
479 |
return; |
|
480 |
} |
|
477 | 481 |
|
478 | 482 |
acb->start = 0; |
479 |
acb->end = (nb_sectors * SECTOR_SIZE); |
|
483 |
acb->end = (acb->nb_sectors * SECTOR_SIZE);
|
|
480 | 484 |
|
481 | 485 |
state->buf_off = 0; |
482 | 486 |
if (state->orig_buf) |
... | ... | |
489 | 493 |
|
490 | 494 |
snprintf(state->range, 127, "%zd-%zd", start, end); |
491 | 495 |
DPRINTF("CURL (AIO): Reading %d at %zd (%s)\n", |
492 |
(nb_sectors * SECTOR_SIZE), start, state->range); |
|
496 |
(acb->nb_sectors * SECTOR_SIZE), start, state->range);
|
|
493 | 497 |
curl_easy_setopt(state->curl, CURLOPT_RANGE, state->range); |
494 | 498 |
|
495 | 499 |
curl_multi_add_handle(s->multi, state->curl); |
496 | 500 |
curl_multi_do(s); |
497 | 501 |
|
502 |
} |
|
503 |
|
|
504 |
static BlockDriverAIOCB *curl_aio_readv(BlockDriverState *bs, |
|
505 |
int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, |
|
506 |
BlockDriverCompletionFunc *cb, void *opaque) |
|
507 |
{ |
|
508 |
CURLAIOCB *acb; |
|
509 |
|
|
510 |
acb = qemu_aio_get(&curl_aio_pool, bs, cb, opaque); |
|
511 |
|
|
512 |
if (!acb) { |
|
513 |
return NULL; |
|
514 |
} |
|
515 |
|
|
516 |
acb->qiov = qiov; |
|
517 |
acb->sector_num = sector_num; |
|
518 |
acb->nb_sectors = nb_sectors; |
|
519 |
|
|
520 |
acb->bh = qemu_bh_new(curl_readv_bh_cb, acb); |
|
521 |
|
|
522 |
if (!acb->bh) { |
|
523 |
DPRINTF("CURL: qemu_bh_new failed\n"); |
|
524 |
return NULL; |
|
525 |
} |
|
526 |
|
|
527 |
qemu_bh_schedule(acb->bh); |
|
498 | 528 |
return &acb->common; |
499 | 529 |
} |
500 | 530 |
|
Also available in: Unified diff