Commit ce1a14dc0d94cf85393356f56f197c5e8b6a7f60
1 parent
51d6bae7
Dynamically allocate AIO Completion Blocks.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2098 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
6 changed files
with
483 additions
and
548 deletions
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, | ... | ... |
block.c
... | ... | @@ -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 */ | ... | ... |
vl.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); | ... | ... |