diff options
author | Anthony Liguori <aliguori@us.ibm.com> | 2012-04-23 14:27:04 -0500 |
---|---|---|
committer | Anthony Liguori <aliguori@us.ibm.com> | 2012-04-23 14:27:04 -0500 |
commit | 1f8bcac09af61e58c5121aa0a932190700ad554d (patch) | |
tree | 4bb240289095295eb5b3806d6347cd866a55a542 /hw | |
parent | cb4c2548ea7cceef7260465773c6b8e634c186d4 (diff) | |
parent | 1042ec94b19e0bfaae74c912ebbdfdbff8dd7db2 (diff) |
Merge remote-tracking branch 'kwolf/for-anthony' into staging
* kwolf/for-anthony: (38 commits)
qemu-iotests: Fix test 031 for qcow2 v3 support
qemu-iotests: Add -o and make v3 the default for qcow2
qcow2: Zero write support
qemu-iotests: Test backing file COW with zero clusters
qemu-iotests: add a simple test for write_zeroes
qcow2: Support for feature table header extension
qcow2: Support reading zero clusters
qcow2: Version 3 images
qcow2: Ignore reserved bits in check_refcounts
qcow2: Ignore reserved bits in refcount table entries
qcow2: Simplify count_cow_clusters
qcow2: Refactor qcow2_free_any_clusters
qcow2: Ignore reserved bits in L1/L2 entries
qcow2: Fail write_compressed when overwriting data
qcow2: Ignore reserved bits in count_contiguous_clusters()
qcow2: Ignore reserved bits in get_cluster_offset
qcow2: Save disk size in snapshot header
Specification for qcow2 version 3
qcow2: Fix refcount block allocation during qcow2_alloc_cluster_at()
iotests: Resolve test failures caused by hostname
...
Diffstat (limited to 'hw')
-rw-r--r-- | hw/ide/core.c | 137 | ||||
-rw-r--r-- | hw/ide/internal.h | 3 |
2 files changed, 100 insertions, 40 deletions
diff --git a/hw/ide/core.c b/hw/ide/core.c index 35723fd800..a5216a6aac 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -471,40 +471,68 @@ static void ide_rw_error(IDEState *s) { ide_set_irq(s->bus); } +static void ide_sector_read_cb(void *opaque, int ret) +{ + IDEState *s = opaque; + int n; + + s->pio_aiocb = NULL; + s->status &= ~BUSY_STAT; + + bdrv_acct_done(s->bs, &s->acct); + if (ret != 0) { + if (ide_handle_rw_error(s, -ret, BM_STATUS_PIO_RETRY | + BM_STATUS_RETRY_READ)) { + return; + } + } + + n = s->nsector; + if (n > s->req_nb_sectors) { + n = s->req_nb_sectors; + } + + /* Allow the guest to read the io_buffer */ + ide_transfer_start(s, s->io_buffer, n * BDRV_SECTOR_SIZE, ide_sector_read); + + ide_set_irq(s->bus); + + ide_set_sector(s, ide_get_sector(s) + n); + s->nsector -= n; +} + void ide_sector_read(IDEState *s) { int64_t sector_num; - int ret, n; + int n; s->status = READY_STAT | SEEK_STAT; s->error = 0; /* not needed by IDE spec, but needed by Windows */ sector_num = ide_get_sector(s); n = s->nsector; + if (n == 0) { - /* no more sector to read from disk */ ide_transfer_stop(s); - } else { + return; + } + + s->status |= BUSY_STAT; + + if (n > s->req_nb_sectors) { + n = s->req_nb_sectors; + } + #if defined(DEBUG_IDE) - printf("read sector=%" PRId64 "\n", sector_num); + printf("sector=%" PRId64 "\n", sector_num); #endif - if (n > s->req_nb_sectors) - n = s->req_nb_sectors; - bdrv_acct_start(s->bs, &s->acct, n * BDRV_SECTOR_SIZE, BDRV_ACCT_READ); - ret = bdrv_read(s->bs, sector_num, s->io_buffer, n); - bdrv_acct_done(s->bs, &s->acct); - if (ret != 0) { - if (ide_handle_rw_error(s, -ret, - BM_STATUS_PIO_RETRY | BM_STATUS_RETRY_READ)) - { - return; - } - } - ide_transfer_start(s, s->io_buffer, 512 * n, ide_sector_read); - ide_set_irq(s->bus); - ide_set_sector(s, sector_num + n); - s->nsector -= n; - } + s->iov.iov_base = s->io_buffer; + s->iov.iov_len = n * BDRV_SECTOR_SIZE; + qemu_iovec_init_external(&s->qiov, &s->iov, 1); + + bdrv_acct_start(s->bs, &s->acct, n * BDRV_SECTOR_SIZE, BDRV_ACCT_READ); + s->pio_aiocb = bdrv_aio_readv(s->bs, sector_num, &s->qiov, n, + ide_sector_read_cb, s); } static void dma_buf_commit(IDEState *s) @@ -660,40 +688,39 @@ static void ide_sector_write_timer_cb(void *opaque) ide_set_irq(s->bus); } -void ide_sector_write(IDEState *s) +static void ide_sector_write_cb(void *opaque, int ret) { - int64_t sector_num; - int ret, n, n1; - - s->status = READY_STAT | SEEK_STAT; - sector_num = ide_get_sector(s); -#if defined(DEBUG_IDE) - printf("write sector=%" PRId64 "\n", sector_num); -#endif - n = s->nsector; - if (n > s->req_nb_sectors) - n = s->req_nb_sectors; + IDEState *s = opaque; + int n; - bdrv_acct_start(s->bs, &s->acct, n * BDRV_SECTOR_SIZE, BDRV_ACCT_READ); - ret = bdrv_write(s->bs, sector_num, s->io_buffer, n); bdrv_acct_done(s->bs, &s->acct); + s->pio_aiocb = NULL; + s->status &= ~BUSY_STAT; + if (ret != 0) { - if (ide_handle_rw_error(s, -ret, BM_STATUS_PIO_RETRY)) + if (ide_handle_rw_error(s, -ret, BM_STATUS_PIO_RETRY)) { return; + } } + n = s->nsector; + if (n > s->req_nb_sectors) { + n = s->req_nb_sectors; + } s->nsector -= n; if (s->nsector == 0) { /* no more sectors to write */ ide_transfer_stop(s); } else { - n1 = s->nsector; - if (n1 > s->req_nb_sectors) + int n1 = s->nsector; + if (n1 > s->req_nb_sectors) { n1 = s->req_nb_sectors; - ide_transfer_start(s, s->io_buffer, 512 * n1, ide_sector_write); + } + ide_transfer_start(s, s->io_buffer, n1 * BDRV_SECTOR_SIZE, + ide_sector_write); } - ide_set_sector(s, sector_num + n); + ide_set_sector(s, ide_get_sector(s) + n); if (win2k_install_hack && ((++s->irq_count % 16) == 0)) { /* It seems there is a bug in the Windows 2000 installer HDD @@ -709,6 +736,30 @@ void ide_sector_write(IDEState *s) } } +void ide_sector_write(IDEState *s) +{ + int64_t sector_num; + int n; + + s->status = READY_STAT | SEEK_STAT | BUSY_STAT; + sector_num = ide_get_sector(s); +#if defined(DEBUG_IDE) + printf("sector=%" PRId64 "\n", sector_num); +#endif + n = s->nsector; + if (n > s->req_nb_sectors) { + n = s->req_nb_sectors; + } + + s->iov.iov_base = s->io_buffer; + s->iov.iov_len = n * BDRV_SECTOR_SIZE; + qemu_iovec_init_external(&s->qiov, &s->iov, 1); + + bdrv_acct_start(s->bs, &s->acct, n * BDRV_SECTOR_SIZE, BDRV_ACCT_READ); + s->pio_aiocb = bdrv_aio_writev(s->bs, sector_num, &s->qiov, n, + ide_sector_write_cb, s); +} + static void ide_flush_cb(void *opaque, int ret) { IDEState *s = opaque; @@ -1765,6 +1816,12 @@ static void ide_reset(IDEState *s) #ifdef DEBUG_IDE printf("ide: reset\n"); #endif + + if (s->pio_aiocb) { + bdrv_aio_cancel(s->pio_aiocb); + s->pio_aiocb = NULL; + } + if (s->drive_kind == IDE_CFATA) s->mult_sectors = 0; else diff --git a/hw/ide/internal.h b/hw/ide/internal.h index 100efd3076..f8a027d0e4 100644 --- a/hw/ide/internal.h +++ b/hw/ide/internal.h @@ -385,6 +385,9 @@ struct IDEState { int cd_sector_size; int atapi_dma; /* true if dma is requested for the packet cmd */ BlockAcctCookie acct; + BlockDriverAIOCB *pio_aiocb; + struct iovec iov; + QEMUIOVector qiov; /* ATA DMA state */ int io_buffer_size; QEMUSGList sg; |