aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorAnthony Liguori <aliguori@us.ibm.com>2012-04-23 14:27:04 -0500
committerAnthony Liguori <aliguori@us.ibm.com>2012-04-23 14:27:04 -0500
commit1f8bcac09af61e58c5121aa0a932190700ad554d (patch)
tree4bb240289095295eb5b3806d6347cd866a55a542 /hw
parentcb4c2548ea7cceef7260465773c6b8e634c186d4 (diff)
parent1042ec94b19e0bfaae74c912ebbdfdbff8dd7db2 (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.c137
-rw-r--r--hw/ide/internal.h3
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;