Revision f141eafe block-qcow.c
b/block-qcow.c | ||
---|---|---|
525 | 525 |
typedef struct QCowAIOCB { |
526 | 526 |
BlockDriverAIOCB common; |
527 | 527 |
int64_t sector_num; |
528 |
QEMUIOVector *qiov; |
|
528 | 529 |
uint8_t *buf; |
530 |
void *orig_buf; |
|
529 | 531 |
int nb_sectors; |
530 | 532 |
int n; |
531 | 533 |
uint64_t cluster_offset; |
... | ... | |
543 | 545 |
int index_in_cluster; |
544 | 546 |
|
545 | 547 |
acb->hd_aiocb = NULL; |
546 |
if (ret < 0) { |
|
547 |
fail: |
|
548 |
acb->common.cb(acb->common.opaque, ret); |
|
549 |
qemu_aio_release(acb); |
|
550 |
return; |
|
551 |
} |
|
548 |
if (ret < 0) |
|
549 |
goto done; |
|
552 | 550 |
|
553 | 551 |
redo: |
554 | 552 |
/* post process the read buffer */ |
... | ... | |
570 | 568 |
|
571 | 569 |
if (acb->nb_sectors == 0) { |
572 | 570 |
/* request completed */ |
573 |
acb->common.cb(acb->common.opaque, 0); |
|
574 |
qemu_aio_release(acb); |
|
575 |
return; |
|
571 |
ret = 0; |
|
572 |
goto done; |
|
576 | 573 |
} |
577 | 574 |
|
578 | 575 |
/* prepare next AIO request */ |
... | ... | |
592 | 589 |
acb->hd_aiocb = bdrv_aio_readv(bs->backing_hd, acb->sector_num, |
593 | 590 |
&acb->hd_qiov, acb->n, qcow_aio_read_cb, acb); |
594 | 591 |
if (acb->hd_aiocb == NULL) |
595 |
goto fail;
|
|
592 |
goto done;
|
|
596 | 593 |
} else { |
597 | 594 |
/* Note: in this case, no need to wait */ |
598 | 595 |
memset(acb->buf, 0, 512 * acb->n); |
... | ... | |
601 | 598 |
} else if (acb->cluster_offset & QCOW_OFLAG_COMPRESSED) { |
602 | 599 |
/* add AIO support for compressed blocks ? */ |
603 | 600 |
if (decompress_cluster(s, acb->cluster_offset) < 0) |
604 |
goto fail;
|
|
601 |
goto done;
|
|
605 | 602 |
memcpy(acb->buf, |
606 | 603 |
s->cluster_cache + index_in_cluster * 512, 512 * acb->n); |
607 | 604 |
goto redo; |
608 | 605 |
} else { |
609 | 606 |
if ((acb->cluster_offset & 511) != 0) { |
610 | 607 |
ret = -EIO; |
611 |
goto fail;
|
|
608 |
goto done;
|
|
612 | 609 |
} |
613 | 610 |
acb->hd_iov.iov_base = acb->buf; |
614 | 611 |
acb->hd_iov.iov_len = acb->n * 512; |
... | ... | |
617 | 614 |
(acb->cluster_offset >> 9) + index_in_cluster, |
618 | 615 |
&acb->hd_qiov, acb->n, qcow_aio_read_cb, acb); |
619 | 616 |
if (acb->hd_aiocb == NULL) |
620 |
goto fail; |
|
617 |
goto done; |
|
618 |
} |
|
619 |
|
|
620 |
return; |
|
621 |
|
|
622 |
done: |
|
623 |
if (acb->qiov->niov > 1) { |
|
624 |
qemu_iovec_from_buffer(acb->qiov, acb->orig_buf, acb->qiov->size); |
|
625 |
qemu_vfree(acb->orig_buf); |
|
621 | 626 |
} |
627 |
acb->common.cb(acb->common.opaque, ret); |
|
628 |
qemu_aio_release(acb); |
|
622 | 629 |
} |
623 | 630 |
|
624 |
static BlockDriverAIOCB *qcow_aio_read(BlockDriverState *bs, |
|
625 |
int64_t sector_num, uint8_t *buf, int nb_sectors,
|
|
631 |
static BlockDriverAIOCB *qcow_aio_readv(BlockDriverState *bs,
|
|
632 |
int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
|
|
626 | 633 |
BlockDriverCompletionFunc *cb, void *opaque) |
627 | 634 |
{ |
628 | 635 |
QCowAIOCB *acb; |
... | ... | |
632 | 639 |
return NULL; |
633 | 640 |
acb->hd_aiocb = NULL; |
634 | 641 |
acb->sector_num = sector_num; |
635 |
acb->buf = buf; |
|
642 |
acb->qiov = qiov; |
|
643 |
if (qiov->niov > 1) |
|
644 |
acb->buf = acb->orig_buf = qemu_memalign(512, qiov->size); |
|
645 |
else |
|
646 |
acb->buf = qiov->iov->iov_base; |
|
636 | 647 |
acb->nb_sectors = nb_sectors; |
637 | 648 |
acb->n = 0; |
638 | 649 |
acb->cluster_offset = 0; |
... | ... | |
652 | 663 |
|
653 | 664 |
acb->hd_aiocb = NULL; |
654 | 665 |
|
655 |
if (ret < 0) { |
|
656 |
fail: |
|
657 |
acb->common.cb(acb->common.opaque, ret); |
|
658 |
qemu_aio_release(acb); |
|
659 |
return; |
|
660 |
} |
|
666 |
if (ret < 0) |
|
667 |
goto done; |
|
661 | 668 |
|
662 | 669 |
acb->nb_sectors -= acb->n; |
663 | 670 |
acb->sector_num += acb->n; |
... | ... | |
665 | 672 |
|
666 | 673 |
if (acb->nb_sectors == 0) { |
667 | 674 |
/* request completed */ |
668 |
acb->common.cb(acb->common.opaque, 0); |
|
669 |
qemu_aio_release(acb); |
|
670 |
return; |
|
675 |
ret = 0; |
|
676 |
goto done; |
|
671 | 677 |
} |
672 | 678 |
|
673 | 679 |
index_in_cluster = acb->sector_num & (s->cluster_sectors - 1); |
... | ... | |
679 | 685 |
index_in_cluster + acb->n); |
680 | 686 |
if (!cluster_offset || (cluster_offset & 511) != 0) { |
681 | 687 |
ret = -EIO; |
682 |
goto fail;
|
|
688 |
goto done;
|
|
683 | 689 |
} |
684 | 690 |
if (s->crypt_method) { |
685 | 691 |
if (!acb->cluster_data) { |
686 | 692 |
acb->cluster_data = qemu_mallocz(s->cluster_size); |
687 | 693 |
if (!acb->cluster_data) { |
688 | 694 |
ret = -ENOMEM; |
689 |
goto fail;
|
|
695 |
goto done;
|
|
690 | 696 |
} |
691 | 697 |
} |
692 | 698 |
encrypt_sectors(s, acb->sector_num, acb->cluster_data, acb->buf, |
... | ... | |
704 | 710 |
&acb->hd_qiov, acb->n, |
705 | 711 |
qcow_aio_write_cb, acb); |
706 | 712 |
if (acb->hd_aiocb == NULL) |
707 |
goto fail; |
|
713 |
goto done; |
|
714 |
return; |
|
715 |
|
|
716 |
done: |
|
717 |
if (acb->qiov->niov > 1) |
|
718 |
qemu_vfree(acb->orig_buf); |
|
719 |
acb->common.cb(acb->common.opaque, ret); |
|
720 |
qemu_aio_release(acb); |
|
708 | 721 |
} |
709 | 722 |
|
710 |
static BlockDriverAIOCB *qcow_aio_write(BlockDriverState *bs, |
|
711 |
int64_t sector_num, const uint8_t *buf, int nb_sectors,
|
|
723 |
static BlockDriverAIOCB *qcow_aio_writev(BlockDriverState *bs,
|
|
724 |
int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
|
|
712 | 725 |
BlockDriverCompletionFunc *cb, void *opaque) |
713 | 726 |
{ |
714 | 727 |
BDRVQcowState *s = bs->opaque; |
... | ... | |
721 | 734 |
return NULL; |
722 | 735 |
acb->hd_aiocb = NULL; |
723 | 736 |
acb->sector_num = sector_num; |
724 |
acb->buf = (uint8_t *)buf; |
|
737 |
acb->qiov = qiov; |
|
738 |
if (qiov->niov > 1) { |
|
739 |
acb->buf = acb->orig_buf = qemu_memalign(512, qiov->size); |
|
740 |
qemu_iovec_to_buffer(qiov, acb->buf); |
|
741 |
} else |
|
742 |
acb->buf = qiov->iov->iov_base; |
|
725 | 743 |
acb->nb_sectors = nb_sectors; |
726 | 744 |
acb->n = 0; |
727 | 745 |
|
... | ... | |
909 | 927 |
.bdrv_is_allocated = qcow_is_allocated, |
910 | 928 |
.bdrv_set_key = qcow_set_key, |
911 | 929 |
.bdrv_make_empty = qcow_make_empty, |
912 |
.bdrv_aio_read = qcow_aio_read,
|
|
913 |
.bdrv_aio_write = qcow_aio_write,
|
|
930 |
.bdrv_aio_readv = qcow_aio_readv,
|
|
931 |
.bdrv_aio_writev = qcow_aio_writev,
|
|
914 | 932 |
.bdrv_aio_cancel = qcow_aio_cancel, |
915 | 933 |
.aiocb_size = sizeof(QCowAIOCB), |
916 | 934 |
.bdrv_write_compressed = qcow_write_compressed, |
Also available in: Unified diff