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); | ... | ... |