Commit ce1a14dc0d94cf85393356f56f197c5e8b6a7f60

Authored by pbrook
1 parent 51d6bae7

Dynamically allocate AIO Completion Blocks.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2098 c046a42c-6fe2-441c-8c8c-71466251a162
block-qcow.c
... ... @@ -522,7 +522,8 @@ static int qcow_write(BlockDriverState *bs, int64_t sector_num,
522 522 return 0;
523 523 }
524 524  
525   -typedef struct {
  525 +typedef struct QCowAIOCB {
  526 + BlockDriverAIOCB common;
526 527 int64_t sector_num;
527 528 uint8_t *buf;
528 529 int nb_sectors;
... ... @@ -530,223 +531,198 @@ typedef struct {
530 531 uint64_t cluster_offset;
531 532 uint8_t *cluster_data;
532 533 BlockDriverAIOCB *hd_aiocb;
533   - BlockDriverAIOCB *backing_hd_aiocb;
534 534 } QCowAIOCB;
535 535  
536   -static void qcow_aio_delete(BlockDriverAIOCB *acb);
537   -
538   -static int qcow_aio_new(BlockDriverAIOCB *acb)
539   -{
540   - BlockDriverState *bs = acb->bs;
541   - BDRVQcowState *s = bs->opaque;
542   - QCowAIOCB *acb1;
543   - acb1 = qemu_mallocz(sizeof(QCowAIOCB));
544   - if (!acb1)
545   - return -1;
546   - acb->opaque = acb1;
547   - acb1->hd_aiocb = bdrv_aio_new(s->hd);
548   - if (!acb1->hd_aiocb)
549   - goto fail;
550   - if (bs->backing_hd) {
551   - acb1->backing_hd_aiocb = bdrv_aio_new(bs->backing_hd);
552   - if (!acb1->backing_hd_aiocb)
553   - goto fail;
554   - }
555   - return 0;
556   - fail:
557   - qcow_aio_delete(acb);
558   - return -1;
559   -}
560   -
561 536 static void qcow_aio_read_cb(void *opaque, int ret)
562 537 {
563   - BlockDriverAIOCB *acb = opaque;
564   - BlockDriverState *bs = acb->bs;
  538 + QCowAIOCB *acb = opaque;
  539 + BlockDriverState *bs = acb->common.bs;
565 540 BDRVQcowState *s = bs->opaque;
566   - QCowAIOCB *acb1 = acb->opaque;
567 541 int index_in_cluster;
568 542  
  543 + acb->hd_aiocb = NULL;
569 544 if (ret < 0) {
570 545 fail:
571   - acb->cb(acb->cb_opaque, ret);
  546 + acb->common.cb(acb->common.opaque, ret);
  547 + qemu_aio_release(acb);
572 548 return;
573 549 }
574 550  
575 551 redo:
576 552 /* post process the read buffer */
577   - if (!acb1->cluster_offset) {
  553 + if (!acb->cluster_offset) {
578 554 /* nothing to do */
579   - } else if (acb1->cluster_offset & QCOW_OFLAG_COMPRESSED) {
  555 + } else if (acb->cluster_offset & QCOW_OFLAG_COMPRESSED) {
580 556 /* nothing to do */
581 557 } else {
582 558 if (s->crypt_method) {
583   - encrypt_sectors(s, acb1->sector_num, acb1->buf, acb1->buf,
584   - acb1->n, 0,
  559 + encrypt_sectors(s, acb->sector_num, acb->buf, acb->buf,
  560 + acb->n, 0,
585 561 &s->aes_decrypt_key);
586 562 }
587 563 }
588 564  
589   - acb1->nb_sectors -= acb1->n;
590   - acb1->sector_num += acb1->n;
591   - acb1->buf += acb1->n * 512;
  565 + acb->nb_sectors -= acb->n;
  566 + acb->sector_num += acb->n;
  567 + acb->buf += acb->n * 512;
592 568  
593   - if (acb1->nb_sectors == 0) {
  569 + if (acb->nb_sectors == 0) {
594 570 /* request completed */
595   - acb->cb(acb->cb_opaque, 0);
  571 + acb->common.cb(acb->common.opaque, 0);
  572 + qemu_aio_release(acb);
596 573 return;
597 574 }
598 575  
599 576 /* prepare next AIO request */
600   - acb1->cluster_offset = get_cluster_offset(bs,
601   - acb1->sector_num << 9,
602   - 0, 0, 0, 0);
603   - index_in_cluster = acb1->sector_num & (s->cluster_sectors - 1);
604   - acb1->n = s->cluster_sectors - index_in_cluster;
605   - if (acb1->n > acb1->nb_sectors)
606   - acb1->n = acb1->nb_sectors;
607   -
608   - if (!acb1->cluster_offset) {
  577 + acb->cluster_offset = get_cluster_offset(bs, acb->sector_num << 9,
  578 + 0, 0, 0, 0);
  579 + index_in_cluster = acb->sector_num & (s->cluster_sectors - 1);
  580 + acb->n = s->cluster_sectors - index_in_cluster;
  581 + if (acb->n > acb->nb_sectors)
  582 + acb->n = acb->nb_sectors;
  583 +
  584 + if (!acb->cluster_offset) {
609 585 if (bs->backing_hd) {
610 586 /* read from the base image */
611   - ret = bdrv_aio_read(acb1->backing_hd_aiocb, acb1->sector_num,
612   - acb1->buf, acb1->n, qcow_aio_read_cb, acb);
613   - if (ret < 0)
  587 + acb->hd_aiocb = bdrv_aio_read(bs->backing_hd,
  588 + acb->sector_num, acb->buf, acb->n, qcow_aio_read_cb, acb);
  589 + if (acb->hd_aiocb == NULL)
614 590 goto fail;
615 591 } else {
616 592 /* Note: in this case, no need to wait */
617   - memset(acb1->buf, 0, 512 * acb1->n);
  593 + memset(acb->buf, 0, 512 * acb->n);
618 594 goto redo;
619 595 }
620   - } else if (acb1->cluster_offset & QCOW_OFLAG_COMPRESSED) {
  596 + } else if (acb->cluster_offset & QCOW_OFLAG_COMPRESSED) {
621 597 /* add AIO support for compressed blocks ? */
622   - if (decompress_cluster(s, acb1->cluster_offset) < 0)
  598 + if (decompress_cluster(s, acb->cluster_offset) < 0)
623 599 goto fail;
624   - memcpy(acb1->buf,
625   - s->cluster_cache + index_in_cluster * 512, 512 * acb1->n);
  600 + memcpy(acb->buf,
  601 + s->cluster_cache + index_in_cluster * 512, 512 * acb->n);
626 602 goto redo;
627 603 } else {
628   - if ((acb1->cluster_offset & 511) != 0) {
  604 + if ((acb->cluster_offset & 511) != 0) {
629 605 ret = -EIO;
630 606 goto fail;
631 607 }
632   - ret = bdrv_aio_read(acb1->hd_aiocb,
633   - (acb1->cluster_offset >> 9) + index_in_cluster,
634   - acb1->buf, acb1->n, qcow_aio_read_cb, acb);
635   - if (ret < 0)
  608 + acb->hd_aiocb = bdrv_aio_read(s->hd,
  609 + (acb->cluster_offset >> 9) + index_in_cluster,
  610 + acb->buf, acb->n, qcow_aio_read_cb, acb);
  611 + if (acb->hd_aiocb == NULL)
636 612 goto fail;
637 613 }
638 614 }
639 615  
640   -static int qcow_aio_read(BlockDriverAIOCB *acb, int64_t sector_num,
641   - uint8_t *buf, int nb_sectors)
  616 +static BlockDriverAIOCB *qcow_aio_read(BlockDriverState *bs,
  617 + int64_t sector_num, uint8_t *buf, int nb_sectors,
  618 + BlockDriverCompletionFunc *cb, void *opaque)
642 619 {
643   - QCowAIOCB *acb1 = acb->opaque;
644   -
645   - acb1->sector_num = sector_num;
646   - acb1->buf = buf;
647   - acb1->nb_sectors = nb_sectors;
648   - acb1->n = 0;
649   - acb1->cluster_offset = 0;
  620 + QCowAIOCB *acb;
  621 +
  622 + acb = qemu_aio_get(bs, cb, opaque);
  623 + if (!acb)
  624 + return NULL;
  625 + acb->hd_aiocb = NULL;
  626 + acb->sector_num = sector_num;
  627 + acb->buf = buf;
  628 + acb->nb_sectors = nb_sectors;
  629 + acb->n = 0;
  630 + acb->cluster_offset = 0;
650 631  
651 632 qcow_aio_read_cb(acb, 0);
652   - return 0;
  633 + return &acb->common;
653 634 }
654 635  
655 636 static void qcow_aio_write_cb(void *opaque, int ret)
656 637 {
657   - BlockDriverAIOCB *acb = opaque;
658   - BlockDriverState *bs = acb->bs;
  638 + QCowAIOCB *acb = opaque;
  639 + BlockDriverState *bs = acb->common.bs;
659 640 BDRVQcowState *s = bs->opaque;
660   - QCowAIOCB *acb1 = acb->opaque;
661 641 int index_in_cluster;
662 642 uint64_t cluster_offset;
663 643 const uint8_t *src_buf;
664   -
  644 +
  645 + acb->hd_aiocb = NULL;
  646 +
665 647 if (ret < 0) {
666 648 fail:
667   - acb->cb(acb->cb_opaque, ret);
  649 + acb->common.cb(acb->common.opaque, ret);
  650 + qemu_aio_release(acb);
668 651 return;
669 652 }
670 653  
671   - acb1->nb_sectors -= acb1->n;
672   - acb1->sector_num += acb1->n;
673   - acb1->buf += acb1->n * 512;
  654 + acb->nb_sectors -= acb->n;
  655 + acb->sector_num += acb->n;
  656 + acb->buf += acb->n * 512;
674 657  
675   - if (acb1->nb_sectors == 0) {
  658 + if (acb->nb_sectors == 0) {
676 659 /* request completed */
677   - acb->cb(acb->cb_opaque, 0);
  660 + acb->common.cb(acb->common.opaque, 0);
  661 + qemu_aio_release(acb);
678 662 return;
679 663 }
680 664  
681   - index_in_cluster = acb1->sector_num & (s->cluster_sectors - 1);
682   - acb1->n = s->cluster_sectors - index_in_cluster;
683   - if (acb1->n > acb1->nb_sectors)
684   - acb1->n = acb1->nb_sectors;
685   - cluster_offset = get_cluster_offset(bs, acb1->sector_num << 9, 1, 0,
  665 + index_in_cluster = acb->sector_num & (s->cluster_sectors - 1);
  666 + acb->n = s->cluster_sectors - index_in_cluster;
  667 + if (acb->n > acb->nb_sectors)
  668 + acb->n = acb->nb_sectors;
  669 + cluster_offset = get_cluster_offset(bs, acb->sector_num << 9, 1, 0,
686 670 index_in_cluster,
687   - index_in_cluster + acb1->n);
  671 + index_in_cluster + acb->n);
688 672 if (!cluster_offset || (cluster_offset & 511) != 0) {
689 673 ret = -EIO;
690 674 goto fail;
691 675 }
692 676 if (s->crypt_method) {
693   - if (!acb1->cluster_data) {
694   - acb1->cluster_data = qemu_mallocz(s->cluster_size);
695   - if (!acb1->cluster_data) {
  677 + if (!acb->cluster_data) {
  678 + acb->cluster_data = qemu_mallocz(s->cluster_size);
  679 + if (!acb->cluster_data) {
696 680 ret = -ENOMEM;
697 681 goto fail;
698 682 }
699 683 }
700   - encrypt_sectors(s, acb1->sector_num, acb1->cluster_data, acb1->buf,
701   - acb1->n, 1, &s->aes_encrypt_key);
702   - src_buf = acb1->cluster_data;
  684 + encrypt_sectors(s, acb->sector_num, acb->cluster_data, acb->buf,
  685 + acb->n, 1, &s->aes_encrypt_key);
  686 + src_buf = acb->cluster_data;
703 687 } else {
704   - src_buf = acb1->buf;
  688 + src_buf = acb->buf;
705 689 }
706   - ret = bdrv_aio_write(acb1->hd_aiocb,
707   - (cluster_offset >> 9) + index_in_cluster,
708   - src_buf, acb1->n,
709   - qcow_aio_write_cb, acb);
710   - if (ret < 0)
  690 + acb->hd_aiocb = bdrv_aio_write(s->hd,
  691 + (cluster_offset >> 9) + index_in_cluster,
  692 + src_buf, acb->n,
  693 + qcow_aio_write_cb, acb);
  694 + if (acb->hd_aiocb == NULL)
711 695 goto fail;
712 696 }
713 697  
714   -static int qcow_aio_write(BlockDriverAIOCB *acb, int64_t sector_num,
715   - const uint8_t *buf, int nb_sectors)
  698 +static BlockDriverAIOCB *qcow_aio_write(BlockDriverState *bs,
  699 + int64_t sector_num, const uint8_t *buf, int nb_sectors,
  700 + BlockDriverCompletionFunc *cb, void *opaque)
716 701 {
717   - QCowAIOCB *acb1 = acb->opaque;
718   - BlockDriverState *bs = acb->bs;
719 702 BDRVQcowState *s = bs->opaque;
  703 + QCowAIOCB *acb;
720 704  
721 705 s->cluster_cache_offset = -1; /* disable compressed cache */
722 706  
723   - acb1->sector_num = sector_num;
724   - acb1->buf = (uint8_t *)buf;
725   - acb1->nb_sectors = nb_sectors;
726   - acb1->n = 0;
  707 + acb = qemu_aio_get(bs, cb, opaque);
  708 + if (!acb)
  709 + return NULL;
  710 + acb->hd_aiocb = NULL;
  711 + acb->sector_num = sector_num;
  712 + acb->buf = (uint8_t *)buf;
  713 + acb->nb_sectors = nb_sectors;
  714 + acb->n = 0;
727 715  
728 716 qcow_aio_write_cb(acb, 0);
729   - return 0;
730   -}
731   -
732   -static void qcow_aio_cancel(BlockDriverAIOCB *acb)
733   -{
734   - QCowAIOCB *acb1 = acb->opaque;
735   - if (acb1->hd_aiocb)
736   - bdrv_aio_cancel(acb1->hd_aiocb);
737   - if (acb1->backing_hd_aiocb)
738   - bdrv_aio_cancel(acb1->backing_hd_aiocb);
  717 + return &acb->common;
739 718 }
740 719  
741   -static void qcow_aio_delete(BlockDriverAIOCB *acb)
  720 +static void qcow_aio_cancel(BlockDriverAIOCB *blockacb)
742 721 {
743   - QCowAIOCB *acb1 = acb->opaque;
744   - if (acb1->hd_aiocb)
745   - bdrv_aio_delete(acb1->hd_aiocb);
746   - if (acb1->backing_hd_aiocb)
747   - bdrv_aio_delete(acb1->backing_hd_aiocb);
748   - qemu_free(acb1->cluster_data);
749   - qemu_free(acb1);
  722 + QCowAIOCB *acb = (QCowAIOCB *)blockacb;
  723 + if (acb->hd_aiocb)
  724 + bdrv_aio_cancel(acb->hd_aiocb);
  725 + qemu_aio_release(acb);
750 726 }
751 727  
752 728 static void qcow_close(BlockDriverState *bs)
... ... @@ -920,11 +896,10 @@ BlockDriver bdrv_qcow = {
920 896 qcow_set_key,
921 897 qcow_make_empty,
922 898  
923   - .bdrv_aio_new = qcow_aio_new,
924 899 .bdrv_aio_read = qcow_aio_read,
925 900 .bdrv_aio_write = qcow_aio_write,
926 901 .bdrv_aio_cancel = qcow_aio_cancel,
927   - .bdrv_aio_delete = qcow_aio_delete,
  902 + .aiocb_size = sizeof(QCowAIOCB),
928 903 .bdrv_write_compressed = qcow_write_compressed,
929 904 .bdrv_get_info = qcow_get_info,
930 905 };
... ...
block-qcow2.c
... ... @@ -791,7 +791,8 @@ static int qcow_write(BlockDriverState *bs, int64_t sector_num,
791 791 return 0;
792 792 }
793 793  
794   -typedef struct {
  794 +typedef struct QCowAIOCB {
  795 + BlockDriverAIOCB common;
795 796 int64_t sector_num;
796 797 uint8_t *buf;
797 798 int nb_sectors;
... ... @@ -799,229 +800,211 @@ typedef struct {
799 800 uint64_t cluster_offset;
800 801 uint8_t *cluster_data;
801 802 BlockDriverAIOCB *hd_aiocb;
802   - BlockDriverAIOCB *backing_hd_aiocb;
803 803 } QCowAIOCB;
804 804  
805   -static void qcow_aio_delete(BlockDriverAIOCB *acb);
806   -
807   -static int qcow_aio_new(BlockDriverAIOCB *acb)
808   -{
809   - BlockDriverState *bs = acb->bs;
810   - BDRVQcowState *s = bs->opaque;
811   - QCowAIOCB *acb1;
812   - acb1 = qemu_mallocz(sizeof(QCowAIOCB));
813   - if (!acb1)
814   - return -1;
815   - acb->opaque = acb1;
816   - acb1->hd_aiocb = bdrv_aio_new(s->hd);
817   - if (!acb1->hd_aiocb)
818   - goto fail;
819   - if (bs->backing_hd) {
820   - acb1->backing_hd_aiocb = bdrv_aio_new(bs->backing_hd);
821   - if (!acb1->backing_hd_aiocb)
822   - goto fail;
823   - }
824   - return 0;
825   - fail:
826   - qcow_aio_delete(acb);
827   - return -1;
828   -}
829   -
830 805 static void qcow_aio_read_cb(void *opaque, int ret)
831 806 {
832   - BlockDriverAIOCB *acb = opaque;
833   - BlockDriverState *bs = acb->bs;
  807 + QCowAIOCB *acb = opaque;
  808 + BlockDriverState *bs = acb->common.bs;
834 809 BDRVQcowState *s = bs->opaque;
835   - QCowAIOCB *acb1 = acb->opaque;
836 810 int index_in_cluster, n1;
837 811  
  812 + acb->hd_aiocb = NULL;
838 813 if (ret < 0) {
839 814 fail:
840   - acb->cb(acb->cb_opaque, ret);
  815 + acb->common.cb(acb->common.opaque, ret);
  816 + qemu_aio_release(acb);
841 817 return;
842 818 }
843 819  
844 820 redo:
845 821 /* post process the read buffer */
846   - if (!acb1->cluster_offset) {
  822 + if (!acb->cluster_offset) {
847 823 /* nothing to do */
848   - } else if (acb1->cluster_offset & QCOW_OFLAG_COMPRESSED) {
  824 + } else if (acb->cluster_offset & QCOW_OFLAG_COMPRESSED) {
849 825 /* nothing to do */
850 826 } else {
851 827 if (s->crypt_method) {
852   - encrypt_sectors(s, acb1->sector_num, acb1->buf, acb1->buf,
853   - acb1->n, 0,
  828 + encrypt_sectors(s, acb->sector_num, acb->buf, acb->buf,
  829 + acb->n, 0,
854 830 &s->aes_decrypt_key);
855 831 }
856 832 }
857 833  
858   - acb1->nb_sectors -= acb1->n;
859   - acb1->sector_num += acb1->n;
860   - acb1->buf += acb1->n * 512;
  834 + acb->nb_sectors -= acb->n;
  835 + acb->sector_num += acb->n;
  836 + acb->buf += acb->n * 512;
861 837  
862   - if (acb1->nb_sectors == 0) {
  838 + if (acb->nb_sectors == 0) {
863 839 /* request completed */
864   - acb->cb(acb->cb_opaque, 0);
  840 + acb->common.cb(acb->common.opaque, 0);
  841 + qemu_aio_release(acb);
865 842 return;
866 843 }
867 844  
868 845 /* prepare next AIO request */
869   - acb1->cluster_offset = get_cluster_offset(bs,
870   - acb1->sector_num << 9,
871   - 0, 0, 0, 0);
872   - index_in_cluster = acb1->sector_num & (s->cluster_sectors - 1);
873   - acb1->n = s->cluster_sectors - index_in_cluster;
874   - if (acb1->n > acb1->nb_sectors)
875   - acb1->n = acb1->nb_sectors;
876   -
877   - if (!acb1->cluster_offset) {
  846 + acb->cluster_offset = get_cluster_offset(bs, acb->sector_num << 9,
  847 + 0, 0, 0, 0);
  848 + index_in_cluster = acb->sector_num & (s->cluster_sectors - 1);
  849 + acb->n = s->cluster_sectors - index_in_cluster;
  850 + if (acb->n > acb->nb_sectors)
  851 + acb->n = acb->nb_sectors;
  852 +
  853 + if (!acb->cluster_offset) {
878 854 if (bs->backing_hd) {
879 855 /* read from the base image */
880   - n1 = backing_read1(bs->backing_hd, acb1->sector_num,
881   - acb1->buf, acb1->n);
  856 + n1 = backing_read1(bs->backing_hd, acb->sector_num,
  857 + acb->buf, acb->n);
882 858 if (n1 > 0) {
883   - ret = bdrv_aio_read(acb1->backing_hd_aiocb, acb1->sector_num,
884   - acb1->buf, n1, qcow_aio_read_cb, acb);
885   - if (ret < 0)
  859 + acb->hd_aiocb = bdrv_aio_read(bs->backing_hd, acb->sector_num,
  860 + acb->buf, acb->n, qcow_aio_read_cb, acb);
  861 + if (acb->hd_aiocb == NULL)
886 862 goto fail;
887 863 } else {
888 864 goto redo;
889 865 }
890 866 } else {
891 867 /* Note: in this case, no need to wait */
892   - memset(acb1->buf, 0, 512 * acb1->n);
  868 + memset(acb->buf, 0, 512 * acb->n);
893 869 goto redo;
894 870 }
895   - } else if (acb1->cluster_offset & QCOW_OFLAG_COMPRESSED) {
  871 + } else if (acb->cluster_offset & QCOW_OFLAG_COMPRESSED) {
896 872 /* add AIO support for compressed blocks ? */
897   - if (decompress_cluster(s, acb1->cluster_offset) < 0)
  873 + if (decompress_cluster(s, acb->cluster_offset) < 0)
898 874 goto fail;
899   - memcpy(acb1->buf,
900   - s->cluster_cache + index_in_cluster * 512, 512 * acb1->n);
  875 + memcpy(acb->buf,
  876 + s->cluster_cache + index_in_cluster * 512, 512 * acb->n);
901 877 goto redo;
902 878 } else {
903   - if ((acb1->cluster_offset & 511) != 0) {
  879 + if ((acb->cluster_offset & 511) != 0) {
904 880 ret = -EIO;
905 881 goto fail;
906 882 }
907   - ret = bdrv_aio_read(acb1->hd_aiocb,
908   - (acb1->cluster_offset >> 9) + index_in_cluster,
909   - acb1->buf, acb1->n, qcow_aio_read_cb, acb);
910   - if (ret < 0)
  883 + acb->hd_aiocb = bdrv_aio_read(s->hd,
  884 + (acb->cluster_offset >> 9) + index_in_cluster,
  885 + acb->buf, acb->n, qcow_aio_read_cb, acb);
  886 + if (acb->hd_aiocb == NULL)
911 887 goto fail;
912 888 }
913 889 }
914 890  
915   -static int qcow_aio_read(BlockDriverAIOCB *acb, int64_t sector_num,
916   - uint8_t *buf, int nb_sectors)
  891 +static QCowAIOCB *qcow_aio_setup(BlockDriverState *bs,
  892 + int64_t sector_num, uint8_t *buf, int nb_sectors,
  893 + BlockDriverCompletionFunc *cb, void *opaque)
917 894 {
918   - QCowAIOCB *acb1 = acb->opaque;
919   -
920   - acb1->sector_num = sector_num;
921   - acb1->buf = buf;
922   - acb1->nb_sectors = nb_sectors;
923   - acb1->n = 0;
924   - acb1->cluster_offset = 0;
  895 + QCowAIOCB *acb;
  896 +
  897 + acb = qemu_aio_get(bs, cb, opaque);
  898 + if (!acb)
  899 + return NULL;
  900 + acb->hd_aiocb = NULL;
  901 + acb->sector_num = sector_num;
  902 + acb->buf = buf;
  903 + acb->nb_sectors = nb_sectors;
  904 + acb->n = 0;
  905 + acb->cluster_offset = 0;
  906 + return acb;
  907 +}
  908 +
  909 +static BlockDriverAIOCB *qcow_aio_read(BlockDriverState *bs,
  910 + int64_t sector_num, uint8_t *buf, int nb_sectors,
  911 + BlockDriverCompletionFunc *cb, void *opaque)
  912 +{
  913 + QCowAIOCB *acb;
  914 +
  915 + acb = qcow_aio_setup(bs, sector_num, buf, nb_sectors, cb, opaque);
  916 + if (!acb)
  917 + return NULL;
925 918  
926 919 qcow_aio_read_cb(acb, 0);
927   - return 0;
  920 + return &acb->common;
928 921 }
929 922  
930 923 static void qcow_aio_write_cb(void *opaque, int ret)
931 924 {
932   - BlockDriverAIOCB *acb = opaque;
933   - BlockDriverState *bs = acb->bs;
  925 + QCowAIOCB *acb = opaque;
  926 + BlockDriverState *bs = acb->common.bs;
934 927 BDRVQcowState *s = bs->opaque;
935   - QCowAIOCB *acb1 = acb->opaque;
936 928 int index_in_cluster;
937 929 uint64_t cluster_offset;
938 930 const uint8_t *src_buf;
939   -
  931 +
  932 + acb->hd_aiocb = NULL;
  933 +
940 934 if (ret < 0) {
941 935 fail:
942   - acb->cb(acb->cb_opaque, ret);
  936 + acb->common.cb(acb->common.opaque, ret);
  937 + qemu_aio_release(acb);
943 938 return;
944 939 }
945 940  
946   - acb1->nb_sectors -= acb1->n;
947   - acb1->sector_num += acb1->n;
948   - acb1->buf += acb1->n * 512;
  941 + acb->nb_sectors -= acb->n;
  942 + acb->sector_num += acb->n;
  943 + acb->buf += acb->n * 512;
949 944  
950   - if (acb1->nb_sectors == 0) {
  945 + if (acb->nb_sectors == 0) {
951 946 /* request completed */
952   - acb->cb(acb->cb_opaque, 0);
  947 + acb->common.cb(acb->common.opaque, 0);
  948 + qemu_aio_release(acb);
953 949 return;
954 950 }
955 951  
956   - index_in_cluster = acb1->sector_num & (s->cluster_sectors - 1);
957   - acb1->n = s->cluster_sectors - index_in_cluster;
958   - if (acb1->n > acb1->nb_sectors)
959   - acb1->n = acb1->nb_sectors;
960   - cluster_offset = get_cluster_offset(bs, acb1->sector_num << 9, 1, 0,
  952 + index_in_cluster = acb->sector_num & (s->cluster_sectors - 1);
  953 + acb->n = s->cluster_sectors - index_in_cluster;
  954 + if (acb->n > acb->nb_sectors)
  955 + acb->n = acb->nb_sectors;
  956 + cluster_offset = get_cluster_offset(bs, acb->sector_num << 9, 1, 0,
961 957 index_in_cluster,
962   - index_in_cluster + acb1->n);
  958 + index_in_cluster + acb->n);
963 959 if (!cluster_offset || (cluster_offset & 511) != 0) {
964 960 ret = -EIO;
965 961 goto fail;
966 962 }
967 963 if (s->crypt_method) {
968   - if (!acb1->cluster_data) {
969   - acb1->cluster_data = qemu_mallocz(s->cluster_size);
970   - if (!acb1->cluster_data) {
  964 + if (!acb->cluster_data) {
  965 + acb->cluster_data = qemu_mallocz(s->cluster_size);
  966 + if (!acb->cluster_data) {
971 967 ret = -ENOMEM;
972 968 goto fail;
973 969 }
974 970 }
975   - encrypt_sectors(s, acb1->sector_num, acb1->cluster_data, acb1->buf,
976   - acb1->n, 1, &s->aes_encrypt_key);
977   - src_buf = acb1->cluster_data;
  971 + encrypt_sectors(s, acb->sector_num, acb->cluster_data, acb->buf,
  972 + acb->n, 1, &s->aes_encrypt_key);
  973 + src_buf = acb->cluster_data;
978 974 } else {
979   - src_buf = acb1->buf;
  975 + src_buf = acb->buf;
980 976 }
981   - ret = bdrv_aio_write(acb1->hd_aiocb,
982   - (cluster_offset >> 9) + index_in_cluster,
983   - src_buf, acb1->n,
984   - qcow_aio_write_cb, acb);
985   - if (ret < 0)
  977 + acb->hd_aiocb = bdrv_aio_write(s->hd,
  978 + (cluster_offset >> 9) + index_in_cluster,
  979 + src_buf, acb->n,
  980 + qcow_aio_write_cb, acb);
  981 + if (acb->hd_aiocb == NULL)
986 982 goto fail;
987 983 }
988 984  
989   -static int qcow_aio_write(BlockDriverAIOCB *acb, int64_t sector_num,
990   - const uint8_t *buf, int nb_sectors)
  985 +static BlockDriverAIOCB *qcow_aio_write(BlockDriverState *bs,
  986 + int64_t sector_num, const uint8_t *buf, int nb_sectors,
  987 + BlockDriverCompletionFunc *cb, void *opaque)
991 988 {
992   - QCowAIOCB *acb1 = acb->opaque;
993   - BlockDriverState *bs = acb->bs;
994 989 BDRVQcowState *s = bs->opaque;
  990 + QCowAIOCB *acb;
995 991  
996 992 s->cluster_cache_offset = -1; /* disable compressed cache */
997 993  
998   - acb1->sector_num = sector_num;
999   - acb1->buf = (uint8_t *)buf;
1000   - acb1->nb_sectors = nb_sectors;
1001   - acb1->n = 0;
  994 + acb = qcow_aio_setup(bs, sector_num, (uint8_t*)buf, nb_sectors, cb, opaque);
  995 + if (!acb)
  996 + return NULL;
1002 997  
1003 998 qcow_aio_write_cb(acb, 0);
1004   - return 0;
1005   -}
1006   -
1007   -static void qcow_aio_cancel(BlockDriverAIOCB *acb)
1008   -{
1009   - QCowAIOCB *acb1 = acb->opaque;
1010   - if (acb1->hd_aiocb)
1011   - bdrv_aio_cancel(acb1->hd_aiocb);
1012   - if (acb1->backing_hd_aiocb)
1013   - bdrv_aio_cancel(acb1->backing_hd_aiocb);
  999 + return &acb->common;
1014 1000 }
1015 1001  
1016   -static void qcow_aio_delete(BlockDriverAIOCB *acb)
  1002 +static void qcow_aio_cancel(BlockDriverAIOCB *blockacb)
1017 1003 {
1018   - QCowAIOCB *acb1 = acb->opaque;
1019   - if (acb1->hd_aiocb)
1020   - bdrv_aio_delete(acb1->hd_aiocb);
1021   - if (acb1->backing_hd_aiocb)
1022   - bdrv_aio_delete(acb1->backing_hd_aiocb);
1023   - qemu_free(acb1->cluster_data);
1024   - qemu_free(acb1);
  1004 + QCowAIOCB *acb = (QCowAIOCB *)blockacb;
  1005 + if (acb->hd_aiocb)
  1006 + bdrv_aio_cancel(acb->hd_aiocb);
  1007 + qemu_aio_release(acb);
1025 1008 }
1026 1009  
1027 1010 static void qcow_close(BlockDriverState *bs)
... ... @@ -2249,11 +2232,10 @@ BlockDriver bdrv_qcow2 = {
2249 2232 qcow_set_key,
2250 2233 qcow_make_empty,
2251 2234  
2252   - .bdrv_aio_new = qcow_aio_new,
2253 2235 .bdrv_aio_read = qcow_aio_read,
2254 2236 .bdrv_aio_write = qcow_aio_write,
2255 2237 .bdrv_aio_cancel = qcow_aio_cancel,
2256   - .bdrv_aio_delete = qcow_aio_delete,
  2238 + .aiocb_size = sizeof(QCowAIOCB),
2257 2239 .bdrv_write_compressed = qcow_write_compressed,
2258 2240  
2259 2241 .bdrv_snapshot_create = qcow_snapshot_create,
... ...
block-raw.c
... ... @@ -200,13 +200,13 @@ static int raw_pwrite(BlockDriverState *bs, int64_t offset,
200 200 /* Unix AOP using POSIX AIO */
201 201  
202 202 typedef struct RawAIOCB {
  203 + BlockDriverAIOCB common;
203 204 struct aiocb aiocb;
204   - int busy; /* only used for debugging */
205   - BlockDriverAIOCB *next;
  205 + struct RawAIOCB *next;
206 206 } RawAIOCB;
207 207  
208 208 static int aio_sig_num = SIGUSR2;
209   -static BlockDriverAIOCB *first_aio; /* AIO issued */
  209 +static RawAIOCB *first_aio; /* AIO issued */
210 210 static int aio_initialized = 0;
211 211  
212 212 static void aio_signal_handler(int signum)
... ... @@ -249,8 +249,7 @@ void qemu_aio_init(void)
249 249  
250 250 void qemu_aio_poll(void)
251 251 {
252   - BlockDriverAIOCB *acb, **pacb;
253   - RawAIOCB *acb1;
  252 + RawAIOCB *acb, **pacb;
254 253 int ret;
255 254  
256 255 for(;;) {
... ... @@ -259,17 +258,16 @@ void qemu_aio_poll(void)
259 258 acb = *pacb;
260 259 if (!acb)
261 260 goto the_end;
262   - acb1 = acb->opaque;
263   - ret = aio_error(&acb1->aiocb);
  261 + ret = aio_error(&acb->aiocb);
264 262 if (ret == ECANCELED) {
265 263 /* remove the request */
266   - acb1->busy = 0;
267   - *pacb = acb1->next;
  264 + *pacb = acb->next;
  265 + qemu_aio_release(acb);
268 266 } else if (ret != EINPROGRESS) {
269 267 /* end of aio */
270 268 if (ret == 0) {
271   - ret = aio_return(&acb1->aiocb);
272   - if (ret == acb1->aiocb.aio_nbytes)
  269 + ret = aio_return(&acb->aiocb);
  270 + if (ret == acb->aiocb.aio_nbytes)
273 271 ret = 0;
274 272 else
275 273 ret = -1;
... ... @@ -277,13 +275,13 @@ void qemu_aio_poll(void)
277 275 ret = -ret;
278 276 }
279 277 /* remove the request */
280   - acb1->busy = 0;
281   - *pacb = acb1->next;
  278 + *pacb = acb->next;
282 279 /* call the callback */
283   - acb->cb(acb->cb_opaque, ret);
  280 + acb->common.cb(acb->common.opaque, ret);
  281 + qemu_aio_release(acb);
284 282 break;
285 283 } else {
286   - pacb = &acb1->next;
  284 + pacb = &acb->next;
287 285 }
288 286 }
289 287 }
... ... @@ -324,70 +322,70 @@ void qemu_aio_wait_end(void)
324 322 sigprocmask(SIG_SETMASK, &wait_oset, NULL);
325 323 }
326 324  
327   -static int raw_aio_new(BlockDriverAIOCB *acb)
  325 +static RawAIOCB *raw_aio_setup(BlockDriverState *bs,
  326 + int64_t sector_num, uint8_t *buf, int nb_sectors,
  327 + BlockDriverCompletionFunc *cb, void *opaque)
328 328 {
329   - RawAIOCB *acb1;
330   - BDRVRawState *s = acb->bs->opaque;
331   -
332   - acb1 = qemu_mallocz(sizeof(RawAIOCB));
333   - if (!acb1)
334   - return -1;
335   - acb->opaque = acb1;
336   - acb1->aiocb.aio_fildes = s->fd;
337   - acb1->aiocb.aio_sigevent.sigev_signo = aio_sig_num;
338   - acb1->aiocb.aio_sigevent.sigev_notify = SIGEV_SIGNAL;
339   - return 0;
  329 + BDRVRawState *s = bs->opaque;
  330 + RawAIOCB *acb;
  331 +
  332 + acb = qemu_aio_get(bs, cb, opaque);
  333 + if (!acb)
  334 + return NULL;
  335 + acb->aiocb.aio_fildes = s->fd;
  336 + acb->aiocb.aio_sigevent.sigev_signo = aio_sig_num;
  337 + acb->aiocb.aio_sigevent.sigev_notify = SIGEV_SIGNAL;
  338 + acb->aiocb.aio_buf = buf;
  339 + acb->aiocb.aio_nbytes = nb_sectors * 512;
  340 + acb->aiocb.aio_offset = sector_num * 512;
  341 + acb->next = first_aio;
  342 + first_aio = acb;
  343 + return acb;
340 344 }
341 345  
342   -static int raw_aio_read(BlockDriverAIOCB *acb, int64_t sector_num,
343   - uint8_t *buf, int nb_sectors)
  346 +static BlockDriverAIOCB *raw_aio_read(BlockDriverState *bs,
  347 + int64_t sector_num, uint8_t *buf, int nb_sectors,
  348 + BlockDriverCompletionFunc *cb, void *opaque)
344 349 {
345   - RawAIOCB *acb1 = acb->opaque;
  350 + RawAIOCB *acb;
346 351  
347   - assert(acb1->busy == 0);
348   - acb1->busy = 1;
349   - acb1->aiocb.aio_buf = buf;
350   - acb1->aiocb.aio_nbytes = nb_sectors * 512;
351   - acb1->aiocb.aio_offset = sector_num * 512;
352   - acb1->next = first_aio;
353   - first_aio = acb;
354   - if (aio_read(&acb1->aiocb) < 0) {
355   - acb1->busy = 0;
356   - return -errno;
  352 + acb = raw_aio_setup(bs, sector_num, buf, nb_sectors, cb, opaque);
  353 + if (!acb)
  354 + return NULL;
  355 + if (aio_read(&acb->aiocb) < 0) {
  356 + qemu_aio_release(acb);
  357 + return NULL;
357 358 }
358   - return 0;
  359 + return &acb->common;
359 360 }
360 361  
361   -static int raw_aio_write(BlockDriverAIOCB *acb, int64_t sector_num,
362   - const uint8_t *buf, int nb_sectors)
  362 +static BlockDriverAIOCB *raw_aio_write(BlockDriverState *bs,
  363 + int64_t sector_num, const uint8_t *buf, int nb_sectors,
  364 + BlockDriverCompletionFunc *cb, void *opaque)
363 365 {
364   - RawAIOCB *acb1 = acb->opaque;
  366 + RawAIOCB *acb;
365 367  
366   - assert(acb1->busy == 0);
367   - acb1->busy = 1;
368   - acb1->aiocb.aio_buf = (uint8_t *)buf;
369   - acb1->aiocb.aio_nbytes = nb_sectors * 512;
370   - acb1->aiocb.aio_offset = sector_num * 512;
371   - acb1->next = first_aio;
372   - first_aio = acb;
373   - if (aio_write(&acb1->aiocb) < 0) {
374   - acb1->busy = 0;
375   - return -errno;
  368 + acb = raw_aio_setup(bs, sector_num, (uint8_t*)buf, nb_sectors, cb, opaque);
  369 + if (!acb)
  370 + return NULL;
  371 + if (aio_write(&acb->aiocb) < 0) {
  372 + qemu_aio_release(acb);
  373 + return NULL;
376 374 }
377   - return 0;
  375 + return &acb->common;
378 376 }
379 377  
380   -static void raw_aio_cancel(BlockDriverAIOCB *acb)
  378 +static void raw_aio_cancel(BlockDriverAIOCB *blockacb)
381 379 {
382   - RawAIOCB *acb1 = acb->opaque;
383 380 int ret;
384   - BlockDriverAIOCB **pacb;
  381 + RawAIOCB *acb = (RawAIOCB *)blockacb;
  382 + RawAIOCB **pacb;
385 383  
386   - ret = aio_cancel(acb1->aiocb.aio_fildes, &acb1->aiocb);
  384 + ret = aio_cancel(acb->aiocb.aio_fildes, &acb->aiocb);
387 385 if (ret == AIO_NOTCANCELED) {
388 386 /* fail safe: if the aio could not be canceled, we wait for
389 387 it */
390   - while (aio_error(&acb1->aiocb) == EINPROGRESS);
  388 + while (aio_error(&acb->aiocb) == EINPROGRESS);
391 389 }
392 390  
393 391 /* remove the callback from the queue */
... ... @@ -396,22 +394,14 @@ static void raw_aio_cancel(BlockDriverAIOCB *acb)
396 394 if (*pacb == NULL) {
397 395 break;
398 396 } else if (*pacb == acb) {
399   - acb1->busy = 0;
400   - *pacb = acb1->next;
  397 + *pacb = acb->next;
  398 + qemu_aio_release(acb);
401 399 break;
402 400 }
403   - acb1 = (*pacb)->opaque;
404   - pacb = &acb1->next;
  401 + pacb = &acb->next;
405 402 }
406 403 }
407 404  
408   -static void raw_aio_delete(BlockDriverAIOCB *acb)
409   -{
410   - RawAIOCB *acb1 = acb->opaque;
411   - raw_aio_cancel(acb);
412   - qemu_free(acb1);
413   -}
414   -
415 405 static void raw_close(BlockDriverState *bs)
416 406 {
417 407 BDRVRawState *s = bs->opaque;
... ... @@ -508,11 +498,10 @@ BlockDriver bdrv_raw = {
508 498 raw_create,
509 499 raw_flush,
510 500  
511   - .bdrv_aio_new = raw_aio_new,
512 501 .bdrv_aio_read = raw_aio_read,
513 502 .bdrv_aio_write = raw_aio_write,
514 503 .bdrv_aio_cancel = raw_aio_cancel,
515   - .bdrv_aio_delete = raw_aio_delete,
  504 + .aiocb_size = sizeof(RawAIOCB),
516 505 .protocol_name = "file",
517 506 .bdrv_pread = raw_pread,
518 507 .bdrv_pwrite = raw_pwrite,
... ... @@ -530,6 +519,7 @@ typedef struct BDRVRawState {
530 519 } BDRVRawState;
531 520  
532 521 typedef struct RawAIOCB {
  522 + BlockDriverAIOCB common;
533 523 HANDLE hEvent;
534 524 OVERLAPPED ov;
535 525 int count;
... ... @@ -574,6 +564,7 @@ static int raw_open(BlockDriverState *bs, const char *filename, int flags)
574 564 {
575 565 BDRVRawState *s = bs->opaque;
576 566 int access_flags, create_flags;
  567 + DWORD overlapped;
577 568  
578 569 if ((flags & BDRV_O_ACCESS) == O_RDWR) {
579 570 access_flags = GENERIC_READ | GENERIC_WRITE;
... ... @@ -585,9 +576,14 @@ static int raw_open(BlockDriverState *bs, const char *filename, int flags)
585 576 } else {
586 577 create_flags = OPEN_EXISTING;
587 578 }
  579 +#ifdef QEMU_TOOL
  580 + overlapped = 0;
  581 +#else
  582 + overlapped = FILE_FLAG_OVERLAPPED;
  583 +#endif
588 584 s->hfile = CreateFile(filename, access_flags,
589 585 FILE_SHARE_READ, NULL,
590   - create_flags, FILE_FLAG_OVERLAPPED, 0);
  586 + create_flags, overlapped, 0);
591 587 if (s->hfile == INVALID_HANDLE_VALUE)
592 588 return -1;
593 589 return 0;
... ... @@ -637,104 +633,107 @@ static int raw_pwrite(BlockDriverState *bs, int64_t offset,
637 633 return ret_count;
638 634 }
639 635  
640   -static int raw_aio_new(BlockDriverAIOCB *acb)
641   -{
642   - RawAIOCB *acb1;
643   -
644   - acb1 = qemu_mallocz(sizeof(RawAIOCB));
645   - if (!acb1)
646   - return -ENOMEM;
647   - acb->opaque = acb1;
648   - acb1->hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
649   - if (!acb1->hEvent)
650   - return -ENOMEM;
651   - return 0;
652   -}
653 636 #ifndef QEMU_TOOL
654 637 static void raw_aio_cb(void *opaque)
655 638 {
656   - BlockDriverAIOCB *acb = opaque;
657   - BlockDriverState *bs = acb->bs;
  639 + RawAIOCB *acb = opaque;
  640 + BlockDriverState *bs = acb->common.bs;
658 641 BDRVRawState *s = bs->opaque;
659   - RawAIOCB *acb1 = acb->opaque;
660 642 DWORD ret_count;
661 643 int ret;
662 644  
663   - ret = GetOverlappedResult(s->hfile, &acb1->ov, &ret_count, TRUE);
664   - if (!ret || ret_count != acb1->count) {
665   - acb->cb(acb->cb_opaque, -EIO);
  645 + ret = GetOverlappedResult(s->hfile, &acb->ov, &ret_count, TRUE);
  646 + if (!ret || ret_count != acb->count) {
  647 + acb->common.cb(acb->common.opaque, -EIO);
666 648 } else {
667   - acb->cb(acb->cb_opaque, 0);
  649 + acb->common.cb(acb->common.opaque, 0);
668 650 }
669 651 }
670 652 #endif
671   -static int raw_aio_read(BlockDriverAIOCB *acb, int64_t sector_num,
672   - uint8_t *buf, int nb_sectors)
  653 +
  654 +static RawAIOCB *raw_aio_setup(BlockDriverState *bs,
  655 + int64_t sector_num, uint8_t *buf, int nb_sectors,
  656 + BlockDriverCompletionFunc *cb, void *opaque)
673 657 {
674   - BlockDriverState *bs = acb->bs;
675   - BDRVRawState *s = bs->opaque;
676   - RawAIOCB *acb1 = acb->opaque;
677   - int ret;
  658 + RawAIOCB *acb;
678 659 int64_t offset;
679 660  
680   - memset(&acb1->ov, 0, sizeof(acb1->ov));
  661 + acb = qemu_aio_get(bs, cb, opaque);
  662 + if (acb->hEvent) {
  663 + acb->hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
  664 + if (!acb->hEvent) {
  665 + qemu_aio_release(acb);
  666 + return NULL;
  667 + }
  668 + }
  669 + memset(&acb->ov, 0, sizeof(acb->ov));
681 670 offset = sector_num * 512;
682   - acb1->ov.Offset = offset;
683   - acb1->ov.OffsetHigh = offset >> 32;
684   - acb1->ov.hEvent = acb1->hEvent;
685   - acb1->count = nb_sectors * 512;
  671 + acb->ov.Offset = offset;
  672 + acb->ov.OffsetHigh = offset >> 32;
  673 + acb->ov.hEvent = acb->hEvent;
  674 + acb->count = nb_sectors * 512;
686 675 #ifndef QEMU_TOOL
687   - qemu_add_wait_object(acb1->ov.hEvent, raw_aio_cb, acb);
  676 + qemu_add_wait_object(acb->ov.hEvent, raw_aio_cb, acb);
688 677 #endif
689   - ret = ReadFile(s->hfile, buf, acb1->count, NULL, &acb1->ov);
690   - if (!ret)
691   - return -EIO;
692   - return 0;
  678 + return acb;
693 679 }
694 680  
695   -static int raw_aio_write(BlockDriverAIOCB *acb, int64_t sector_num,
696   - uint8_t *buf, int nb_sectors)
  681 +static BlockDriverAIOCB *raw_aio_read(BlockDriverState *bs,
  682 + int64_t sector_num, uint8_t *buf, int nb_sectors,
  683 + BlockDriverCompletionFunc *cb, void *opaque)
697 684 {
698   - BlockDriverState *bs = acb->bs;
699 685 BDRVRawState *s = bs->opaque;
700   - RawAIOCB *acb1 = acb->opaque;
  686 + RawAIOCB *acb;
701 687 int ret;
702   - int64_t offset;
703 688  
704   - memset(&acb1->ov, 0, sizeof(acb1->ov));
705   - offset = sector_num * 512;
706   - acb1->ov.Offset = offset;
707   - acb1->ov.OffsetHigh = offset >> 32;
708   - acb1->ov.hEvent = acb1->hEvent;
709   - acb1->count = nb_sectors * 512;
710   -#ifndef QEMU_TOOL
711   - qemu_add_wait_object(acb1->ov.hEvent, raw_aio_cb, acb);
  689 + acb = raw_aio_setup(bs, sector_num, buf, nb_sectors, cb, opaque);
  690 + if (!acb)
  691 + return NULL;
  692 + ret = ReadFile(s->hfile, buf, acb->count, NULL, &acb->ov);
  693 + if (!ret) {
  694 + qemu_aio_release(acb);
  695 + return NULL;
  696 + }
  697 +#ifdef QEMU_TOOL
  698 + qemu_aio_release(acb);
712 699 #endif
713   - ret = ReadFile(s->hfile, buf, acb1->count, NULL, &acb1->ov);
714   - if (!ret)
715   - return -EIO;
716   - return 0;
  700 + return (BlockDriverAIOCB *)acb;
717 701 }
718 702  
719   -static void raw_aio_cancel(BlockDriverAIOCB *acb)
  703 +static BlockDriverAIOCB *raw_aio_write(BlockDriverState *bs,
  704 + int64_t sector_num, uint8_t *buf, int nb_sectors,
  705 + BlockDriverCompletionFunc *cb, void *opaque)
720 706 {
721   - BlockDriverState *bs = acb->bs;
722 707 BDRVRawState *s = bs->opaque;
723   -#ifndef QEMU_TOOL
724   - RawAIOCB *acb1 = acb->opaque;
  708 + RawAIOCB *acb;
  709 + int ret;
725 710  
726   - qemu_del_wait_object(acb1->ov.hEvent, raw_aio_cb, acb);
  711 + acb = raw_aio_setup(bs, sector_num, buf, nb_sectors, cb, opaque);
  712 + if (!acb)
  713 + return NULL;
  714 + ret = WriteFile(s->hfile, buf, acb->count, NULL, &acb->ov);
  715 + if (!ret) {
  716 + qemu_aio_release(acb);
  717 + return NULL;
  718 + }
  719 +#ifdef QEMU_TOOL
  720 + qemu_aio_release(acb);
727 721 #endif
728   - /* XXX: if more than one async I/O it is not correct */
729   - CancelIo(s->hfile);
  722 + return (BlockDriverAIOCB *)acb;
730 723 }
731 724  
732   -static void raw_aio_delete(BlockDriverAIOCB *acb)
  725 +static void raw_aio_cancel(BlockDriverAIOCB *blockacb)
733 726 {
734   - RawAIOCB *acb1 = acb->opaque;
735   - raw_aio_cancel(acb);
736   - CloseHandle(acb1->hEvent);
737   - qemu_free(acb1);
  727 +#ifndef QEMU_TOOL
  728 + RawAIOCB *acb = (RawAIOCB *)blockacb;
  729 + BlockDriverState *bs = acb->common.bs;
  730 + BDRVRawState *s = bs->opaque;
  731 +
  732 + qemu_del_wait_object(acb->ov.hEvent, raw_aio_cb, acb);
  733 + /* XXX: if more than one async I/O it is not correct */
  734 + CancelIo(s->hfile);
  735 + qemu_aio_release(acb);
  736 +#endif
738 737 }
739 738  
740 739 static void raw_flush(BlockDriverState *bs)
... ... @@ -823,11 +822,10 @@ BlockDriver bdrv_raw = {
823 822 raw_flush,
824 823  
825 824 #if 0
826   - .bdrv_aio_new = raw_aio_new,
827 825 .bdrv_aio_read = raw_aio_read,
828 826 .bdrv_aio_write = raw_aio_write,
829 827 .bdrv_aio_cancel = raw_aio_cancel,
830   - .bdrv_aio_delete = raw_aio_delete,
  828 + .aiocb_size = sizeof(RawAIOCB);
831 829 #endif
832 830 .protocol_name = "file",
833 831 .bdrv_pread = raw_pread,
... ...
... ... @@ -35,13 +35,13 @@
35 35 #define SECTOR_BITS 9
36 36 #define SECTOR_SIZE (1 << SECTOR_BITS)
37 37  
38   -static int bdrv_aio_new_em(BlockDriverAIOCB *acb);
39   -static int bdrv_aio_read_em(BlockDriverAIOCB *acb, int64_t sector_num,
40   - uint8_t *buf, int nb_sectors);
41   -static int bdrv_aio_write_em(BlockDriverAIOCB *acb, int64_t sector_num,
42   - const uint8_t *buf, int nb_sectors);
  38 +static BlockDriverAIOCB *bdrv_aio_read_em(BlockDriverState *bs,
  39 + int64_t sector_num, uint8_t *buf, int nb_sectors,
  40 + BlockDriverCompletionFunc *cb, void *opaque);
  41 +static BlockDriverAIOCB *bdrv_aio_write_em(BlockDriverState *bs,
  42 + int64_t sector_num, const uint8_t *buf, int nb_sectors,
  43 + BlockDriverCompletionFunc *cb, void *opaque);
43 44 static void bdrv_aio_cancel_em(BlockDriverAIOCB *acb);
44   -static void bdrv_aio_delete_em(BlockDriverAIOCB *acb);
45 45 static int bdrv_read_em(BlockDriverState *bs, int64_t sector_num,
46 46 uint8_t *buf, int nb_sectors);
47 47 static int bdrv_write_em(BlockDriverState *bs, int64_t sector_num,
... ... @@ -106,13 +106,11 @@ void path_combine(char *dest, int dest_size,
106 106  
107 107 void bdrv_register(BlockDriver *bdrv)
108 108 {
109   - if (!bdrv->bdrv_aio_new) {
  109 + if (!bdrv->bdrv_aio_read) {
110 110 /* add AIO emulation layer */
111   - bdrv->bdrv_aio_new = bdrv_aio_new_em;
112 111 bdrv->bdrv_aio_read = bdrv_aio_read_em;
113 112 bdrv->bdrv_aio_write = bdrv_aio_write_em;
114 113 bdrv->bdrv_aio_cancel = bdrv_aio_cancel_em;
115   - bdrv->bdrv_aio_delete = bdrv_aio_delete_em;
116 114 } else if (!bdrv->bdrv_read && !bdrv->bdrv_pread) {
117 115 /* add synchronous IO emulation layer */
118 116 bdrv->bdrv_read = bdrv_read_em;
... ... @@ -964,7 +962,9 @@ char *bdrv_snapshot_dump(char *buf, int buf_size, QEMUSnapshotInfo *sn)
964 962 "ID", "TAG", "VM SIZE", "DATE", "VM CLOCK");
965 963 } else {
966 964 ti = sn->date_sec;
  965 +#ifndef _WIN32
967 966 localtime_r(&ti, &tm);
  967 +#endif
968 968 strftime(date_buf, sizeof(date_buf),
969 969 "%Y-%m-%d %H:%M:%S", &tm);
970 970 secs = sn->vm_clock_nsec / 1000000000;
... ... @@ -988,31 +988,14 @@ char *bdrv_snapshot_dump(char *buf, int buf_size, QEMUSnapshotInfo *sn)
988 988 /**************************************************************/
989 989 /* async I/Os */
990 990  
991   -BlockDriverAIOCB *bdrv_aio_new(BlockDriverState *bs)
  991 +BlockDriverAIOCB *bdrv_aio_read(BlockDriverState *bs, int64_t sector_num,
  992 + uint8_t *buf, int nb_sectors,
  993 + BlockDriverCompletionFunc *cb, void *opaque)
992 994 {
993 995 BlockDriver *drv = bs->drv;
994   - BlockDriverAIOCB *acb;
995   - acb = qemu_mallocz(sizeof(BlockDriverAIOCB));
996   - if (!acb)
997   - return NULL;
998   -
999   - acb->bs = bs;
1000   - if (drv->bdrv_aio_new(acb) < 0) {
1001   - qemu_free(acb);
1002   - return NULL;
1003   - }
1004   - return acb;
1005   -}
1006   -
1007   -int bdrv_aio_read(BlockDriverAIOCB *acb, int64_t sector_num,
1008   - uint8_t *buf, int nb_sectors,
1009   - BlockDriverCompletionFunc *cb, void *opaque)
1010   -{
1011   - BlockDriverState *bs = acb->bs;
1012   - BlockDriver *drv = bs->drv;
1013 996  
1014 997 if (!bs->inserted)
1015   - return -1;
  998 + return NULL;
1016 999  
1017 1000 /* XXX: we assume that nb_sectors == 0 is suppored by the async read */
1018 1001 if (sector_num == 0 && bs->boot_sector_enabled && nb_sectors > 0) {
... ... @@ -1022,141 +1005,114 @@ int bdrv_aio_read(BlockDriverAIOCB *acb, int64_t sector_num,
1022 1005 buf += 512;
1023 1006 }
1024 1007  
1025   - acb->cb = cb;
1026   - acb->cb_opaque = opaque;
1027   - return drv->bdrv_aio_read(acb, sector_num, buf, nb_sectors);
  1008 + return drv->bdrv_aio_read(bs, sector_num, buf, nb_sectors, cb, opaque);
1028 1009 }
1029 1010  
1030   -int bdrv_aio_write(BlockDriverAIOCB *acb, int64_t sector_num,
1031   - const uint8_t *buf, int nb_sectors,
1032   - BlockDriverCompletionFunc *cb, void *opaque)
  1011 +BlockDriverAIOCB *bdrv_aio_write(BlockDriverState *bs, int64_t sector_num,
  1012 + const uint8_t *buf, int nb_sectors,
  1013 + BlockDriverCompletionFunc *cb, void *opaque)
1033 1014 {
1034   - BlockDriverState *bs = acb->bs;
1035 1015 BlockDriver *drv = bs->drv;
1036 1016  
1037 1017 if (!bs->inserted)
1038   - return -1;
  1018 + return NULL;
1039 1019 if (bs->read_only)
1040   - return -1;
  1020 + return NULL;
1041 1021 if (sector_num == 0 && bs->boot_sector_enabled && nb_sectors > 0) {
1042 1022 memcpy(bs->boot_sector_data, buf, 512);
1043 1023 }
1044 1024  
1045   - acb->cb = cb;
1046   - acb->cb_opaque = opaque;
1047   - return drv->bdrv_aio_write(acb, sector_num, buf, nb_sectors);
  1025 + return drv->bdrv_aio_write(bs, sector_num, buf, nb_sectors, cb, opaque);
1048 1026 }
1049 1027  
1050 1028 void bdrv_aio_cancel(BlockDriverAIOCB *acb)
1051   - {
1052   - BlockDriverState *bs = acb->bs;
1053   - BlockDriver *drv = bs->drv;
1054   -
1055   - drv->bdrv_aio_cancel(acb);
1056   - }
1057   -
1058   -void bdrv_aio_delete(BlockDriverAIOCB *acb)
1059 1029 {
1060   - BlockDriverState *bs = acb->bs;
1061   - BlockDriver *drv = bs->drv;
  1030 + BlockDriver *drv = acb->bs->drv;
1062 1031  
1063   - drv->bdrv_aio_delete(acb);
1064   - qemu_free(acb);
  1032 + drv->bdrv_aio_cancel(acb);
1065 1033 }
1066 1034  
  1035 +
1067 1036 /**************************************************************/
1068 1037 /* async block device emulation */
1069 1038  
1070 1039 #ifdef QEMU_TOOL
1071   -static int bdrv_aio_new_em(BlockDriverAIOCB *acb)
1072   -{
1073   - return 0;
1074   -}
1075   -
1076   -static int bdrv_aio_read_em(BlockDriverAIOCB *acb, int64_t sector_num,
1077   - uint8_t *buf, int nb_sectors)
  1040 +static BlockDriverAIOCB *bdrv_aio_read_em(BlockDriverState *bs,
  1041 + int64_t sector_num, uint8_t *buf, int nb_sectors,
  1042 + BlockDriverCompletionFunc *cb, void *opaque)
1078 1043 {
1079 1044 int ret;
1080   - ret = bdrv_read(acb->bs, sector_num, buf, nb_sectors);
1081   - acb->cb(acb->cb_opaque, ret);
1082   - return 0;
  1045 + ret = bdrv_read(bs, sector_num, buf, nb_sectors);
  1046 + cb(opaque, ret);
  1047 + return NULL;
1083 1048 }
1084 1049  
1085   -static int bdrv_aio_write_em(BlockDriverAIOCB *acb, int64_t sector_num,
1086   - const uint8_t *buf, int nb_sectors)
  1050 +static BlockDriverAIOCB *bdrv_aio_write_em(BlockDriverState *bs,
  1051 + int64_t sector_num, const uint8_t *buf, int nb_sectors,
  1052 + BlockDriverCompletionFunc *cb, void *opaque)
1087 1053 {
1088 1054 int ret;
1089   - ret = bdrv_write(acb->bs, sector_num, buf, nb_sectors);
1090   - acb->cb(acb->cb_opaque, ret);
1091   - return 0;
  1055 + ret = bdrv_write(bs, sector_num, buf, nb_sectors);
  1056 + cb(opaque, ret);
  1057 + return NULL;
1092 1058 }
1093 1059  
1094 1060 static void bdrv_aio_cancel_em(BlockDriverAIOCB *acb)
1095 1061 {
1096 1062 }
1097   -
1098   -static void bdrv_aio_delete_em(BlockDriverAIOCB *acb)
1099   -{
1100   -}
1101 1063 #else
1102 1064 typedef struct BlockDriverAIOCBSync {
  1065 + BlockDriverAIOCB common;
1103 1066 QEMUBH *bh;
1104 1067 int ret;
1105 1068 } BlockDriverAIOCBSync;
1106 1069  
1107   -static void bdrv_aio_bh_cb(void *opaque)
1108   -{
1109   - BlockDriverAIOCB *acb = opaque;
1110   - BlockDriverAIOCBSync *acb1 = acb->opaque;
1111   - acb->cb(acb->cb_opaque, acb1->ret);
1112   -}
  1070 +static BlockDriverAIOCBSync *free_acb = NULL;
1113 1071  
1114   -static int bdrv_aio_new_em(BlockDriverAIOCB *acb)
  1072 +static void bdrv_aio_bh_cb(void *opaque)
1115 1073 {
1116   - BlockDriverAIOCBSync *acb1;
1117   -
1118   - acb1 = qemu_mallocz(sizeof(BlockDriverAIOCBSync));
1119   - if (!acb1)
1120   - return -1;
1121   - acb->opaque = acb1;
1122   - acb1->bh = qemu_bh_new(bdrv_aio_bh_cb, acb);
1123   - return 0;
  1074 + BlockDriverAIOCBSync *acb = opaque;
  1075 + acb->common.cb(acb->common.opaque, acb->ret);
  1076 + qemu_aio_release(acb);
1124 1077 }
1125 1078  
1126   -static int bdrv_aio_read_em(BlockDriverAIOCB *acb, int64_t sector_num,
1127   - uint8_t *buf, int nb_sectors)
  1079 +static BlockDriverAIOCB *bdrv_aio_read_em(BlockDriverState *bs,
  1080 + int64_t sector_num, uint8_t *buf, int nb_sectors,
  1081 + BlockDriverCompletionFunc *cb, void *opaque)
1128 1082 {
1129   - BlockDriverAIOCBSync *acb1 = acb->opaque;
  1083 + BlockDriverAIOCBSync *acb;
1130 1084 int ret;
1131   -
1132   - ret = bdrv_read(acb->bs, sector_num, buf, nb_sectors);
1133   - acb1->ret = ret;
1134   - qemu_bh_schedule(acb1->bh);
1135   - return 0;
  1085 +
  1086 + acb = qemu_aio_get(bs, cb, opaque);
  1087 + if (!acb->bh)
  1088 + acb->bh = qemu_bh_new(bdrv_aio_bh_cb, acb);
  1089 + ret = bdrv_read(bs, sector_num, buf, nb_sectors);
  1090 + acb->ret = ret;
  1091 + qemu_bh_schedule(acb->bh);
  1092 + return &acb->common;
1136 1093 }
1137 1094  
1138   -static int bdrv_aio_write_em(BlockDriverAIOCB *acb, int64_t sector_num,
1139   - const uint8_t *buf, int nb_sectors)
  1095 +static BlockDriverAIOCB *bdrv_aio_write_em(BlockDriverState *bs,
  1096 + int64_t sector_num, const uint8_t *buf, int nb_sectors,
  1097 + BlockDriverCompletionFunc *cb, void *opaque)
1140 1098 {
1141   - BlockDriverAIOCBSync *acb1 = acb->opaque;
  1099 + BlockDriverAIOCBSync *acb;
1142 1100 int ret;
1143   -
1144   - ret = bdrv_write(acb->bs, sector_num, buf, nb_sectors);
1145   - acb1->ret = ret;
1146   - qemu_bh_schedule(acb1->bh);
1147   - return 0;
1148   -}
1149 1101  
1150   -static void bdrv_aio_cancel_em(BlockDriverAIOCB *acb)
1151   -{
1152   - BlockDriverAIOCBSync *acb1 = acb->opaque;
1153   - qemu_bh_cancel(acb1->bh);
  1102 + acb = qemu_aio_get(bs, cb, opaque);
  1103 + if (!acb->bh)
  1104 + acb->bh = qemu_bh_new(bdrv_aio_bh_cb, acb);
  1105 + ret = bdrv_write(bs, sector_num, buf, nb_sectors);
  1106 + acb->ret = ret;
  1107 + qemu_bh_schedule(acb->bh);
  1108 + return &acb->common;
1154 1109 }
1155 1110  
1156   -static void bdrv_aio_delete_em(BlockDriverAIOCB *acb)
  1111 +static void bdrv_aio_cancel_em(BlockDriverAIOCB *blockacb)
1157 1112 {
1158   - BlockDriverAIOCBSync *acb1 = acb->opaque;
1159   - qemu_bh_delete(acb1->bh);
  1113 + BlockDriverAIOCBSync *acb = (BlockDriverAIOCBSync *)blockacb;
  1114 + qemu_bh_cancel(acb->bh);
  1115 + qemu_aio_release(acb);
1160 1116 }
1161 1117 #endif /* !QEMU_TOOL */
1162 1118  
... ... @@ -1173,20 +1129,16 @@ static void bdrv_rw_em_cb(void *opaque, int ret)
1173 1129 static int bdrv_read_em(BlockDriverState *bs, int64_t sector_num,
1174 1130 uint8_t *buf, int nb_sectors)
1175 1131 {
1176   - int async_ret, ret;
  1132 + int async_ret;
  1133 + BlockDriverAIOCB *acb;
1177 1134  
1178   - if (!bs->sync_aiocb) {
1179   - bs->sync_aiocb = bdrv_aio_new(bs);
1180   - if (!bs->sync_aiocb)
1181   - return -1;
1182   - }
1183 1135 async_ret = NOT_DONE;
1184 1136 qemu_aio_wait_start();
1185   - ret = bdrv_aio_read(bs->sync_aiocb, sector_num, buf, nb_sectors,
  1137 + acb = bdrv_aio_read(bs, sector_num, buf, nb_sectors,
1186 1138 bdrv_rw_em_cb, &async_ret);
1187   - if (ret < 0) {
  1139 + if (acb == NULL) {
1188 1140 qemu_aio_wait_end();
1189   - return ret;
  1141 + return -1;
1190 1142 }
1191 1143 while (async_ret == NOT_DONE) {
1192 1144 qemu_aio_wait();
... ... @@ -1198,20 +1150,16 @@ static int bdrv_read_em(BlockDriverState *bs, int64_t sector_num,
1198 1150 static int bdrv_write_em(BlockDriverState *bs, int64_t sector_num,
1199 1151 const uint8_t *buf, int nb_sectors)
1200 1152 {
1201   - int async_ret, ret;
  1153 + int async_ret;
  1154 + BlockDriverAIOCB *acb;
1202 1155  
1203   - if (!bs->sync_aiocb) {
1204   - bs->sync_aiocb = bdrv_aio_new(bs);
1205   - if (!bs->sync_aiocb)
1206   - return -1;
1207   - }
1208 1156 async_ret = NOT_DONE;
1209 1157 qemu_aio_wait_start();
1210   - ret = bdrv_aio_write(bs->sync_aiocb, sector_num, buf, nb_sectors,
  1158 + acb = bdrv_aio_write(bs, sector_num, buf, nb_sectors,
1211 1159 bdrv_rw_em_cb, &async_ret);
1212   - if (ret < 0) {
  1160 + if (acb == NULL) {
1213 1161 qemu_aio_wait_end();
1214   - return ret;
  1162 + return -1;
1215 1163 }
1216 1164 while (async_ret == NOT_DONE) {
1217 1165 qemu_aio_wait();
... ... @@ -1235,3 +1183,32 @@ void bdrv_init(void)
1235 1183 bdrv_register(&bdrv_vvfat);
1236 1184 bdrv_register(&bdrv_qcow2);
1237 1185 }
  1186 +
  1187 +void *qemu_aio_get(BlockDriverState *bs, BlockDriverCompletionFunc *cb,
  1188 + void *opaque)
  1189 +{
  1190 + BlockDriver *drv;
  1191 + BlockDriverAIOCB *acb;
  1192 +
  1193 + drv = bs->drv;
  1194 + if (drv->free_aiocb) {
  1195 + acb = drv->free_aiocb;
  1196 + drv->free_aiocb = acb->next;
  1197 + } else {
  1198 + acb = qemu_mallocz(drv->aiocb_size);
  1199 + if (!acb)
  1200 + return NULL;
  1201 + }
  1202 + acb->bs = bs;
  1203 + acb->cb = cb;
  1204 + acb->opaque = opaque;
  1205 + return acb;
  1206 +}
  1207 +
  1208 +void qemu_aio_release(void *p)
  1209 +{
  1210 + BlockDriverAIOCB *acb = p;
  1211 + BlockDriver *drv = acb->bs->drv;
  1212 + acb->next = drv->free_aiocb;
  1213 + drv->free_aiocb = acb;
  1214 +}
... ...
block_int.h
... ... @@ -42,13 +42,14 @@ struct BlockDriver {
42 42 int (*bdrv_set_key)(BlockDriverState *bs, const char *key);
43 43 int (*bdrv_make_empty)(BlockDriverState *bs);
44 44 /* aio */
45   - int (*bdrv_aio_new)(BlockDriverAIOCB *acb);
46   - int (*bdrv_aio_read)(BlockDriverAIOCB *acb, int64_t sector_num,
47   - uint8_t *buf, int nb_sectors);
48   - int (*bdrv_aio_write)(BlockDriverAIOCB *acb, int64_t sector_num,
49   - const uint8_t *buf, int nb_sectors);
  45 + BlockDriverAIOCB *(*bdrv_aio_read)(BlockDriverState *bs,
  46 + int64_t sector_num, uint8_t *buf, int nb_sectors,
  47 + BlockDriverCompletionFunc *cb, void *opaque);
  48 + BlockDriverAIOCB *(*bdrv_aio_write)(BlockDriverState *bs,
  49 + int64_t sector_num, const uint8_t *buf, int nb_sectors,
  50 + BlockDriverCompletionFunc *cb, void *opaque);
50 51 void (*bdrv_aio_cancel)(BlockDriverAIOCB *acb);
51   - void (*bdrv_aio_delete)(BlockDriverAIOCB *acb);
  52 + int aiocb_size;
52 53  
53 54 const char *protocol_name;
54 55 int (*bdrv_pread)(BlockDriverState *bs, int64_t offset,
... ... @@ -69,6 +70,7 @@ struct BlockDriver {
69 70 QEMUSnapshotInfo **psn_info);
70 71 int (*bdrv_get_info)(BlockDriverState *bs, BlockDriverInfo *bdi);
71 72  
  73 + BlockDriverAIOCB *free_aiocb;
72 74 struct BlockDriver *next;
73 75 };
74 76  
... ... @@ -96,9 +98,9 @@ struct BlockDriverState {
96 98 int is_temporary;
97 99  
98 100 BlockDriverState *backing_hd;
99   - /* sync read/write emulation */
  101 + /* async read/write emulation */
100 102  
101   - BlockDriverAIOCB *sync_aiocb;
  103 + void *sync_aiocb;
102 104  
103 105 /* NOTE: the following infos are only hints for real hardware
104 106 drivers. They are not used by the block driver */
... ... @@ -111,11 +113,14 @@ struct BlockDriverState {
111 113 struct BlockDriverAIOCB {
112 114 BlockDriverState *bs;
113 115 BlockDriverCompletionFunc *cb;
114   - void *cb_opaque;
115   -
116   - void *opaque; /* driver opaque */
  116 + void *opaque;
  117 + BlockDriverAIOCB *next;
117 118 };
118 119  
119 120 void get_tmp_filename(char *filename, int size);
120 121  
  122 +void *qemu_aio_get(BlockDriverState *bs, BlockDriverCompletionFunc *cb,
  123 + void *opaque);
  124 +void qemu_aio_release(void *p);
  125 +
121 126 #endif /* BLOCK_INT_H */
... ...
... ... @@ -569,15 +569,13 @@ void bdrv_set_boot_sector(BlockDriverState *bs, const uint8_t *data, int size);
569 569 typedef struct BlockDriverAIOCB BlockDriverAIOCB;
570 570 typedef void BlockDriverCompletionFunc(void *opaque, int ret);
571 571  
572   -BlockDriverAIOCB *bdrv_aio_new(BlockDriverState *bs);
573   -int bdrv_aio_read(BlockDriverAIOCB *acb, int64_t sector_num,
574   - uint8_t *buf, int nb_sectors,
575   - BlockDriverCompletionFunc *cb, void *opaque);
576   -int bdrv_aio_write(BlockDriverAIOCB *acb, int64_t sector_num,
577   - const uint8_t *buf, int nb_sectors,
578   - BlockDriverCompletionFunc *cb, void *opaque);
  572 +BlockDriverAIOCB *bdrv_aio_read(BlockDriverState *bs, int64_t sector_num,
  573 + uint8_t *buf, int nb_sectors,
  574 + BlockDriverCompletionFunc *cb, void *opaque);
  575 +BlockDriverAIOCB *bdrv_aio_write(BlockDriverState *bs, int64_t sector_num,
  576 + const uint8_t *buf, int nb_sectors,
  577 + BlockDriverCompletionFunc *cb, void *opaque);
579 578 void bdrv_aio_cancel(BlockDriverAIOCB *acb);
580   -void bdrv_aio_delete(BlockDriverAIOCB *acb);
581 579  
582 580 void qemu_aio_init(void);
583 581 void qemu_aio_poll(void);
... ...