Dynamically allocate AIO Completion Blocks.
authorpbrook <pbrook@c046a42c-6fe2-441c-8c8c-71466251a162>
Mon, 7 Aug 2006 02:38:06 +0000 (02:38 +0000)
committerpbrook <pbrook@c046a42c-6fe2-441c-8c8c-71466251a162>
Mon, 7 Aug 2006 02:38:06 +0000 (02:38 +0000)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2098 c046a42c-6fe2-441c-8c8c-71466251a162

block-qcow.c
block-qcow2.c
block-raw.c
block.c
block_int.h
vl.h

index 151ec85..d5333b3 100644 (file)
@@ -522,7 +522,8 @@ static int qcow_write(BlockDriverState *bs, int64_t sector_num,
     return 0;
 }
 
-typedef struct {
+typedef struct QCowAIOCB {
+    BlockDriverAIOCB common;
     int64_t sector_num;
     uint8_t *buf;
     int nb_sectors;
@@ -530,223 +531,198 @@ typedef struct {
     uint64_t cluster_offset;
     uint8_t *cluster_data; 
     BlockDriverAIOCB *hd_aiocb;
-    BlockDriverAIOCB *backing_hd_aiocb;
 } QCowAIOCB;
 
-static void qcow_aio_delete(BlockDriverAIOCB *acb);
-
-static int qcow_aio_new(BlockDriverAIOCB *acb)
-{
-    BlockDriverState *bs = acb->bs;
-    BDRVQcowState *s = bs->opaque;
-    QCowAIOCB *acb1;
-    acb1 = qemu_mallocz(sizeof(QCowAIOCB));
-    if (!acb1)
-        return -1;
-    acb->opaque = acb1;
-    acb1->hd_aiocb = bdrv_aio_new(s->hd);
-    if (!acb1->hd_aiocb)
-        goto fail;
-    if (bs->backing_hd) {
-        acb1->backing_hd_aiocb = bdrv_aio_new(bs->backing_hd);
-        if (!acb1->backing_hd_aiocb)
-            goto fail;
-    }
-    return 0;
- fail:
-    qcow_aio_delete(acb);
-    return -1;
-}
-
 static void qcow_aio_read_cb(void *opaque, int ret)
 {
-    BlockDriverAIOCB *acb = opaque;
-    BlockDriverState *bs = acb->bs;
+    QCowAIOCB *acb = opaque;
+    BlockDriverState *bs = acb->common.bs;
     BDRVQcowState *s = bs->opaque;
-    QCowAIOCB *acb1 = acb->opaque;
     int index_in_cluster;
 
+    acb->hd_aiocb = NULL;
     if (ret < 0) {
     fail:
-        acb->cb(acb->cb_opaque, ret);
+        acb->common.cb(acb->common.opaque, ret);
+        qemu_aio_release(acb);
         return;
     }
 
  redo:
     /* post process the read buffer */
-    if (!acb1->cluster_offset) {
+    if (!acb->cluster_offset) {
         /* nothing to do */
-    } else if (acb1->cluster_offset & QCOW_OFLAG_COMPRESSED) {
+    } else if (acb->cluster_offset & QCOW_OFLAG_COMPRESSED) {
         /* nothing to do */
     } else {
         if (s->crypt_method) {
-            encrypt_sectors(s, acb1->sector_num, acb1->buf, acb1->buf, 
-                            acb1->n, 0, 
+            encrypt_sectors(s, acb->sector_num, acb->buf, acb->buf, 
+                            acb->n, 0, 
                             &s->aes_decrypt_key);
         }
     }
 
-    acb1->nb_sectors -= acb1->n;
-    acb1->sector_num += acb1->n;
-    acb1->buf += acb1->n * 512;
+    acb->nb_sectors -= acb->n;
+    acb->sector_num += acb->n;
+    acb->buf += acb->n * 512;
 
-    if (acb1->nb_sectors == 0) {
+    if (acb->nb_sectors == 0) {
         /* request completed */
-        acb->cb(acb->cb_opaque, 0);
+        acb->common.cb(acb->common.opaque, 0);
+        qemu_aio_release(acb);
         return;
     }
     
     /* prepare next AIO request */
-    acb1->cluster_offset = get_cluster_offset(bs, 
-                                              acb1->sector_num << 9, 
-                                              0, 0, 0, 0);
-    index_in_cluster = acb1->sector_num & (s->cluster_sectors - 1);
-    acb1->n = s->cluster_sectors - index_in_cluster;
-    if (acb1->n > acb1->nb_sectors)
-        acb1->n = acb1->nb_sectors;
-
-    if (!acb1->cluster_offset) {
+    acb->cluster_offset = get_cluster_offset(bs, acb->sector_num << 9, 
+                                             0, 0, 0, 0);
+    index_in_cluster = acb->sector_num & (s->cluster_sectors - 1);
+    acb->n = s->cluster_sectors - index_in_cluster;
+    if (acb->n > acb->nb_sectors)
+        acb->n = acb->nb_sectors;
+
+    if (!acb->cluster_offset) {
         if (bs->backing_hd) {
             /* read from the base image */
-            ret = bdrv_aio_read(acb1->backing_hd_aiocb, acb1->sector_num, 
-                                acb1->buf, acb1->n, qcow_aio_read_cb, acb);
-            if (ret < 0)
+            acb->hd_aiocb = bdrv_aio_read(bs->backing_hd,
+                acb->sector_num, acb->buf, acb->n, qcow_aio_read_cb, acb);
+            if (acb->hd_aiocb == NULL)
                 goto fail;
         } else {
             /* Note: in this case, no need to wait */
-            memset(acb1->buf, 0, 512 * acb1->n);
+            memset(acb->buf, 0, 512 * acb->n);
             goto redo;
         }
-    } else if (acb1->cluster_offset & QCOW_OFLAG_COMPRESSED) {
+    } else if (acb->cluster_offset & QCOW_OFLAG_COMPRESSED) {
         /* add AIO support for compressed blocks ? */
-        if (decompress_cluster(s, acb1->cluster_offset) < 0)
+        if (decompress_cluster(s, acb->cluster_offset) < 0)
             goto fail;
-        memcpy(acb1->buf, 
-               s->cluster_cache + index_in_cluster * 512, 512 * acb1->n);
+        memcpy(acb->buf, 
+               s->cluster_cache + index_in_cluster * 512, 512 * acb->n);
         goto redo;
     } else {
-        if ((acb1->cluster_offset & 511) != 0) {
+        if ((acb->cluster_offset & 511) != 0) {
             ret = -EIO;
             goto fail;
         }
-        ret = bdrv_aio_read(acb1->hd_aiocb, 
-                            (acb1->cluster_offset >> 9) + index_in_cluster, 
-                            acb1->buf, acb1->n, qcow_aio_read_cb, acb);
-        if (ret < 0)
+        acb->hd_aiocb = bdrv_aio_read(s->hd,
+                            (acb->cluster_offset >> 9) + index_in_cluster, 
+                            acb->buf, acb->n, qcow_aio_read_cb, acb);
+        if (acb->hd_aiocb == NULL)
             goto fail;
     }
 }
 
-static int qcow_aio_read(BlockDriverAIOCB *acb, int64_t sector_num, 
-                         uint8_t *buf, int nb_sectors)
+static BlockDriverAIOCB *qcow_aio_read(BlockDriverState *bs,
+        int64_t sector_num, uint8_t *buf, int nb_sectors,
+        BlockDriverCompletionFunc *cb, void *opaque)
 {
-    QCowAIOCB *acb1 = acb->opaque;
-    
-    acb1->sector_num = sector_num;
-    acb1->buf = buf;
-    acb1->nb_sectors = nb_sectors;
-    acb1->n = 0;
-    acb1->cluster_offset = 0;    
+    QCowAIOCB *acb;
+
+    acb = qemu_aio_get(bs, cb, opaque);
+    if (!acb)
+        return NULL;
+    acb->hd_aiocb = NULL;
+    acb->sector_num = sector_num;
+    acb->buf = buf;
+    acb->nb_sectors = nb_sectors;
+    acb->n = 0;
+    acb->cluster_offset = 0;    
 
     qcow_aio_read_cb(acb, 0);
-    return 0;
+    return &acb->common;
 }
 
 static void qcow_aio_write_cb(void *opaque, int ret)
 {
-    BlockDriverAIOCB *acb = opaque;
-    BlockDriverState *bs = acb->bs;
+    QCowAIOCB *acb = opaque;
+    BlockDriverState *bs = acb->common.bs;
     BDRVQcowState *s = bs->opaque;
-    QCowAIOCB *acb1 = acb->opaque;
     int index_in_cluster;
     uint64_t cluster_offset;
     const uint8_t *src_buf;
-    
+
+    acb->hd_aiocb = NULL;
+
     if (ret < 0) {
     fail:
-        acb->cb(acb->cb_opaque, ret);
+        acb->common.cb(acb->common.opaque, ret);
+        qemu_aio_release(acb);
         return;
     }
 
-    acb1->nb_sectors -= acb1->n;
-    acb1->sector_num += acb1->n;
-    acb1->buf += acb1->n * 512;
+    acb->nb_sectors -= acb->n;
+    acb->sector_num += acb->n;
+    acb->buf += acb->n * 512;
 
-    if (acb1->nb_sectors == 0) {
+    if (acb->nb_sectors == 0) {
         /* request completed */
-        acb->cb(acb->cb_opaque, 0);
+        acb->common.cb(acb->common.opaque, 0);
+        qemu_aio_release(acb);
         return;
     }
     
-    index_in_cluster = acb1->sector_num & (s->cluster_sectors - 1);
-    acb1->n = s->cluster_sectors - index_in_cluster;
-    if (acb1->n > acb1->nb_sectors)
-        acb1->n = acb1->nb_sectors;
-    cluster_offset = get_cluster_offset(bs, acb1->sector_num << 9, 1, 0, 
+    index_in_cluster = acb->sector_num & (s->cluster_sectors - 1);
+    acb->n = s->cluster_sectors - index_in_cluster;
+    if (acb->n > acb->nb_sectors)
+        acb->n = acb->nb_sectors;
+    cluster_offset = get_cluster_offset(bs, acb->sector_num << 9, 1, 0, 
                                         index_in_cluster, 
-                                        index_in_cluster + acb1->n);
+                                        index_in_cluster + acb->n);
     if (!cluster_offset || (cluster_offset & 511) != 0) {
         ret = -EIO;
         goto fail;
     }
     if (s->crypt_method) {
-        if (!acb1->cluster_data) {
-            acb1->cluster_data = qemu_mallocz(s->cluster_size);
-            if (!acb1->cluster_data) {
+        if (!acb->cluster_data) {
+            acb->cluster_data = qemu_mallocz(s->cluster_size);
+            if (!acb->cluster_data) {
                 ret = -ENOMEM;
                 goto fail;
             }
         }
-        encrypt_sectors(s, acb1->sector_num, acb1->cluster_data, acb1->buf, 
-                        acb1->n, 1, &s->aes_encrypt_key);
-        src_buf = acb1->cluster_data;
+        encrypt_sectors(s, acb->sector_num, acb->cluster_data, acb->buf, 
+                        acb->n, 1, &s->aes_encrypt_key);
+        src_buf = acb->cluster_data;
     } else {
-        src_buf = acb1->buf;
+        src_buf = acb->buf;
     }
-    ret = bdrv_aio_write(acb1->hd_aiocb, 
-                         (cluster_offset >> 9) + index_in_cluster, 
-                         src_buf, acb1->n, 
-                         qcow_aio_write_cb, acb);
-    if (ret < 0)
+    acb->hd_aiocb = bdrv_aio_write(s->hd,
+                                   (cluster_offset >> 9) + index_in_cluster, 
+                                   src_buf, acb->n, 
+                                   qcow_aio_write_cb, acb);
+    if (acb->hd_aiocb == NULL)
         goto fail;
 }
 
-static int qcow_aio_write(BlockDriverAIOCB *acb, int64_t sector_num, 
-                          const uint8_t *buf, int nb_sectors)
+static BlockDriverAIOCB *qcow_aio_write(BlockDriverState *bs,
+        int64_t sector_num, const uint8_t *buf, int nb_sectors,
+        BlockDriverCompletionFunc *cb, void *opaque)
 {
-    QCowAIOCB *acb1 = acb->opaque;
-    BlockDriverState *bs = acb->bs;
     BDRVQcowState *s = bs->opaque;
+    QCowAIOCB *acb;
     
     s->cluster_cache_offset = -1; /* disable compressed cache */
 
-    acb1->sector_num = sector_num;
-    acb1->buf = (uint8_t *)buf;
-    acb1->nb_sectors = nb_sectors;
-    acb1->n = 0;
+    acb = qemu_aio_get(bs, cb, opaque);
+    if (!acb)
+        return NULL;
+    acb->hd_aiocb = NULL;
+    acb->sector_num = sector_num;
+    acb->buf = (uint8_t *)buf;
+    acb->nb_sectors = nb_sectors;
+    acb->n = 0;
     
     qcow_aio_write_cb(acb, 0);
-    return 0;
-}
-
-static void qcow_aio_cancel(BlockDriverAIOCB *acb)
-{
-    QCowAIOCB *acb1 = acb->opaque;
-    if (acb1->hd_aiocb)
-        bdrv_aio_cancel(acb1->hd_aiocb);
-    if (acb1->backing_hd_aiocb)
-        bdrv_aio_cancel(acb1->backing_hd_aiocb);
+    return &acb->common;
 }
 
-static void qcow_aio_delete(BlockDriverAIOCB *acb)
+static void qcow_aio_cancel(BlockDriverAIOCB *blockacb)
 {
-    QCowAIOCB *acb1 = acb->opaque;
-    if (acb1->hd_aiocb)
-        bdrv_aio_delete(acb1->hd_aiocb);
-    if (acb1->backing_hd_aiocb)
-        bdrv_aio_delete(acb1->backing_hd_aiocb);
-    qemu_free(acb1->cluster_data);
-    qemu_free(acb1);
+    QCowAIOCB *acb = (QCowAIOCB *)blockacb;
+    if (acb->hd_aiocb)
+        bdrv_aio_cancel(acb->hd_aiocb);
+    qemu_aio_release(acb);
 }
 
 static void qcow_close(BlockDriverState *bs)
@@ -920,11 +896,10 @@ BlockDriver bdrv_qcow = {
     qcow_set_key,
     qcow_make_empty,
 
-    .bdrv_aio_new = qcow_aio_new,
     .bdrv_aio_read = qcow_aio_read,
     .bdrv_aio_write = qcow_aio_write,
     .bdrv_aio_cancel = qcow_aio_cancel,
-    .bdrv_aio_delete = qcow_aio_delete,
+    .aiocb_size = sizeof(QCowAIOCB),
     .bdrv_write_compressed = qcow_write_compressed,
     .bdrv_get_info = qcow_get_info,
 };
index bc2aa14..a876ea2 100644 (file)
@@ -791,7 +791,8 @@ static int qcow_write(BlockDriverState *bs, int64_t sector_num,
     return 0;
 }
 
-typedef struct {
+typedef struct QCowAIOCB {
+    BlockDriverAIOCB common;
     int64_t sector_num;
     uint8_t *buf;
     int nb_sectors;
@@ -799,229 +800,211 @@ typedef struct {
     uint64_t cluster_offset;
     uint8_t *cluster_data; 
     BlockDriverAIOCB *hd_aiocb;
-    BlockDriverAIOCB *backing_hd_aiocb;
 } QCowAIOCB;
 
-static void qcow_aio_delete(BlockDriverAIOCB *acb);
-
-static int qcow_aio_new(BlockDriverAIOCB *acb)
-{
-    BlockDriverState *bs = acb->bs;
-    BDRVQcowState *s = bs->opaque;
-    QCowAIOCB *acb1;
-    acb1 = qemu_mallocz(sizeof(QCowAIOCB));
-    if (!acb1)
-        return -1;
-    acb->opaque = acb1;
-    acb1->hd_aiocb = bdrv_aio_new(s->hd);
-    if (!acb1->hd_aiocb)
-        goto fail;
-    if (bs->backing_hd) {
-        acb1->backing_hd_aiocb = bdrv_aio_new(bs->backing_hd);
-        if (!acb1->backing_hd_aiocb)
-            goto fail;
-    }
-    return 0;
- fail:
-    qcow_aio_delete(acb);
-    return -1;
-}
-
 static void qcow_aio_read_cb(void *opaque, int ret)
 {
-    BlockDriverAIOCB *acb = opaque;
-    BlockDriverState *bs = acb->bs;
+    QCowAIOCB *acb = opaque;
+    BlockDriverState *bs = acb->common.bs;
     BDRVQcowState *s = bs->opaque;
-    QCowAIOCB *acb1 = acb->opaque;
     int index_in_cluster, n1;
 
+    acb->hd_aiocb = NULL;
     if (ret < 0) {
     fail:
-        acb->cb(acb->cb_opaque, ret);
+        acb->common.cb(acb->common.opaque, ret);
+        qemu_aio_release(acb);
         return;
     }
 
  redo:
     /* post process the read buffer */
-    if (!acb1->cluster_offset) {
+    if (!acb->cluster_offset) {
         /* nothing to do */
-    } else if (acb1->cluster_offset & QCOW_OFLAG_COMPRESSED) {
+    } else if (acb->cluster_offset & QCOW_OFLAG_COMPRESSED) {
         /* nothing to do */
     } else {
         if (s->crypt_method) {
-            encrypt_sectors(s, acb1->sector_num, acb1->buf, acb1->buf, 
-                            acb1->n, 0, 
+            encrypt_sectors(s, acb->sector_num, acb->buf, acb->buf, 
+                            acb->n, 0, 
                             &s->aes_decrypt_key);
         }
     }
 
-    acb1->nb_sectors -= acb1->n;
-    acb1->sector_num += acb1->n;
-    acb1->buf += acb1->n * 512;
+    acb->nb_sectors -= acb->n;
+    acb->sector_num += acb->n;
+    acb->buf += acb->n * 512;
 
-    if (acb1->nb_sectors == 0) {
+    if (acb->nb_sectors == 0) {
         /* request completed */
-        acb->cb(acb->cb_opaque, 0);
+        acb->common.cb(acb->common.opaque, 0);
+        qemu_aio_release(acb);
         return;
     }
     
     /* prepare next AIO request */
-    acb1->cluster_offset = get_cluster_offset(bs, 
-                                              acb1->sector_num << 9, 
-                                              0, 0, 0, 0);
-    index_in_cluster = acb1->sector_num & (s->cluster_sectors - 1);
-    acb1->n = s->cluster_sectors - index_in_cluster;
-    if (acb1->n > acb1->nb_sectors)
-        acb1->n = acb1->nb_sectors;
-
-    if (!acb1->cluster_offset) {
+    acb->cluster_offset = get_cluster_offset(bs, acb->sector_num << 9, 
+                                             0, 0, 0, 0);
+    index_in_cluster = acb->sector_num & (s->cluster_sectors - 1);
+    acb->n = s->cluster_sectors - index_in_cluster;
+    if (acb->n > acb->nb_sectors)
+        acb->n = acb->nb_sectors;
+
+    if (!acb->cluster_offset) {
         if (bs->backing_hd) {
             /* read from the base image */
-            n1 = backing_read1(bs->backing_hd, acb1->sector_num, 
-                               acb1->buf, acb1->n);
+            n1 = backing_read1(bs->backing_hd, acb->sector_num, 
+                               acb->buf, acb->n);
             if (n1 > 0) {
-                ret = bdrv_aio_read(acb1->backing_hd_aiocb, acb1->sector_num, 
-                                    acb1->buf, n1, qcow_aio_read_cb, acb);
-                if (ret < 0)
+                acb->hd_aiocb = bdrv_aio_read(bs->backing_hd, acb->sector_num, 
+                                    acb->buf, acb->n, qcow_aio_read_cb, acb);
+                if (acb->hd_aiocb == NULL)
                     goto fail;
             } else {
                 goto redo;
             }
         } else {
             /* Note: in this case, no need to wait */
-            memset(acb1->buf, 0, 512 * acb1->n);
+            memset(acb->buf, 0, 512 * acb->n);
             goto redo;
         }
-    } else if (acb1->cluster_offset & QCOW_OFLAG_COMPRESSED) {
+    } else if (acb->cluster_offset & QCOW_OFLAG_COMPRESSED) {
         /* add AIO support for compressed blocks ? */
-        if (decompress_cluster(s, acb1->cluster_offset) < 0)
+        if (decompress_cluster(s, acb->cluster_offset) < 0)
             goto fail;
-        memcpy(acb1->buf, 
-               s->cluster_cache + index_in_cluster * 512, 512 * acb1->n);
+        memcpy(acb->buf, 
+               s->cluster_cache + index_in_cluster * 512, 512 * acb->n);
         goto redo;
     } else {
-        if ((acb1->cluster_offset & 511) != 0) {
+        if ((acb->cluster_offset & 511) != 0) {
             ret = -EIO;
             goto fail;
         }
-        ret = bdrv_aio_read(acb1->hd_aiocb, 
-                            (acb1->cluster_offset >> 9) + index_in_cluster, 
-                            acb1->buf, acb1->n, qcow_aio_read_cb, acb);
-        if (ret < 0)
+        acb->hd_aiocb = bdrv_aio_read(s->hd,
+                            (acb->cluster_offset >> 9) + index_in_cluster, 
+                            acb->buf, acb->n, qcow_aio_read_cb, acb);
+        if (acb->hd_aiocb == NULL)
             goto fail;
     }
 }
 
-static int qcow_aio_read(BlockDriverAIOCB *acb, int64_t sector_num, 
-                         uint8_t *buf, int nb_sectors)
+static QCowAIOCB *qcow_aio_setup(BlockDriverState *bs,
+        int64_t sector_num, uint8_t *buf, int nb_sectors,
+        BlockDriverCompletionFunc *cb, void *opaque)
 {
-    QCowAIOCB *acb1 = acb->opaque;
-    
-    acb1->sector_num = sector_num;
-    acb1->buf = buf;
-    acb1->nb_sectors = nb_sectors;
-    acb1->n = 0;
-    acb1->cluster_offset = 0;    
+    QCowAIOCB *acb;
+
+    acb = qemu_aio_get(bs, cb, opaque);
+    if (!acb)
+        return NULL;
+    acb->hd_aiocb = NULL;
+    acb->sector_num = sector_num;
+    acb->buf = buf;
+    acb->nb_sectors = nb_sectors;
+    acb->n = 0;
+    acb->cluster_offset = 0;
+    return acb;
+}
+
+static BlockDriverAIOCB *qcow_aio_read(BlockDriverState *bs,
+        int64_t sector_num, uint8_t *buf, int nb_sectors,
+        BlockDriverCompletionFunc *cb, void *opaque)
+{
+    QCowAIOCB *acb;
+
+    acb = qcow_aio_setup(bs, sector_num, buf, nb_sectors, cb, opaque);
+    if (!acb)
+        return NULL;
 
     qcow_aio_read_cb(acb, 0);
-    return 0;
+    return &acb->common;
 }
 
 static void qcow_aio_write_cb(void *opaque, int ret)
 {
-    BlockDriverAIOCB *acb = opaque;
-    BlockDriverState *bs = acb->bs;
+    QCowAIOCB *acb = opaque;
+    BlockDriverState *bs = acb->common.bs;
     BDRVQcowState *s = bs->opaque;
-    QCowAIOCB *acb1 = acb->opaque;
     int index_in_cluster;
     uint64_t cluster_offset;
     const uint8_t *src_buf;
-    
+
+    acb->hd_aiocb = NULL;
+
     if (ret < 0) {
     fail:
-        acb->cb(acb->cb_opaque, ret);
+        acb->common.cb(acb->common.opaque, ret);
+        qemu_aio_release(acb);
         return;
     }
 
-    acb1->nb_sectors -= acb1->n;
-    acb1->sector_num += acb1->n;
-    acb1->buf += acb1->n * 512;
+    acb->nb_sectors -= acb->n;
+    acb->sector_num += acb->n;
+    acb->buf += acb->n * 512;
 
-    if (acb1->nb_sectors == 0) {
+    if (acb->nb_sectors == 0) {
         /* request completed */
-        acb->cb(acb->cb_opaque, 0);
+        acb->common.cb(acb->common.opaque, 0);
+        qemu_aio_release(acb);
         return;
     }
     
-    index_in_cluster = acb1->sector_num & (s->cluster_sectors - 1);
-    acb1->n = s->cluster_sectors - index_in_cluster;
-    if (acb1->n > acb1->nb_sectors)
-        acb1->n = acb1->nb_sectors;
-    cluster_offset = get_cluster_offset(bs, acb1->sector_num << 9, 1, 0, 
+    index_in_cluster = acb->sector_num & (s->cluster_sectors - 1);
+    acb->n = s->cluster_sectors - index_in_cluster;
+    if (acb->n > acb->nb_sectors)
+        acb->n = acb->nb_sectors;
+    cluster_offset = get_cluster_offset(bs, acb->sector_num << 9, 1, 0, 
                                         index_in_cluster, 
-                                        index_in_cluster + acb1->n);
+                                        index_in_cluster + acb->n);
     if (!cluster_offset || (cluster_offset & 511) != 0) {
         ret = -EIO;
         goto fail;
     }
     if (s->crypt_method) {
-        if (!acb1->cluster_data) {
-            acb1->cluster_data = qemu_mallocz(s->cluster_size);
-            if (!acb1->cluster_data) {
+        if (!acb->cluster_data) {
+            acb->cluster_data = qemu_mallocz(s->cluster_size);
+            if (!acb->cluster_data) {
                 ret = -ENOMEM;
                 goto fail;
             }
         }
-        encrypt_sectors(s, acb1->sector_num, acb1->cluster_data, acb1->buf, 
-                        acb1->n, 1, &s->aes_encrypt_key);
-        src_buf = acb1->cluster_data;
+        encrypt_sectors(s, acb->sector_num, acb->cluster_data, acb->buf, 
+                        acb->n, 1, &s->aes_encrypt_key);
+        src_buf = acb->cluster_data;
     } else {
-        src_buf = acb1->buf;
+        src_buf = acb->buf;
     }
-    ret = bdrv_aio_write(acb1->hd_aiocb, 
-                         (cluster_offset >> 9) + index_in_cluster, 
-                         src_buf, acb1->n, 
-                         qcow_aio_write_cb, acb);
-    if (ret < 0)
+    acb->hd_aiocb = bdrv_aio_write(s->hd,
+                                   (cluster_offset >> 9) + index_in_cluster, 
+                                   src_buf, acb->n, 
+                                   qcow_aio_write_cb, acb);
+    if (acb->hd_aiocb == NULL)
         goto fail;
 }
 
-static int qcow_aio_write(BlockDriverAIOCB *acb, int64_t sector_num, 
-                          const uint8_t *buf, int nb_sectors)
+static BlockDriverAIOCB *qcow_aio_write(BlockDriverState *bs,
+        int64_t sector_num, const uint8_t *buf, int nb_sectors,
+        BlockDriverCompletionFunc *cb, void *opaque)
 {
-    QCowAIOCB *acb1 = acb->opaque;
-    BlockDriverState *bs = acb->bs;
     BDRVQcowState *s = bs->opaque;
+    QCowAIOCB *acb;
     
     s->cluster_cache_offset = -1; /* disable compressed cache */
 
-    acb1->sector_num = sector_num;
-    acb1->buf = (uint8_t *)buf;
-    acb1->nb_sectors = nb_sectors;
-    acb1->n = 0;
+    acb = qcow_aio_setup(bs, sector_num, (uint8_t*)buf, nb_sectors, cb, opaque);
+    if (!acb)
+        return NULL;
     
     qcow_aio_write_cb(acb, 0);
-    return 0;
-}
-
-static void qcow_aio_cancel(BlockDriverAIOCB *acb)
-{
-    QCowAIOCB *acb1 = acb->opaque;
-    if (acb1->hd_aiocb)
-        bdrv_aio_cancel(acb1->hd_aiocb);
-    if (acb1->backing_hd_aiocb)
-        bdrv_aio_cancel(acb1->backing_hd_aiocb);
+    return &acb->common;
 }
 
-static void qcow_aio_delete(BlockDriverAIOCB *acb)
+static void qcow_aio_cancel(BlockDriverAIOCB *blockacb)
 {
-    QCowAIOCB *acb1 = acb->opaque;
-    if (acb1->hd_aiocb)
-        bdrv_aio_delete(acb1->hd_aiocb);
-    if (acb1->backing_hd_aiocb)
-        bdrv_aio_delete(acb1->backing_hd_aiocb);
-    qemu_free(acb1->cluster_data);
-    qemu_free(acb1);
+    QCowAIOCB *acb = (QCowAIOCB *)blockacb;
+    if (acb->hd_aiocb)
+        bdrv_aio_cancel(acb->hd_aiocb);
+    qemu_aio_release(acb);
 }
 
 static void qcow_close(BlockDriverState *bs)
@@ -2249,11 +2232,10 @@ BlockDriver bdrv_qcow2 = {
     qcow_set_key,
     qcow_make_empty,
 
-    .bdrv_aio_new = qcow_aio_new,
     .bdrv_aio_read = qcow_aio_read,
     .bdrv_aio_write = qcow_aio_write,
     .bdrv_aio_cancel = qcow_aio_cancel,
-    .bdrv_aio_delete = qcow_aio_delete,
+    .aiocb_size = sizeof(QCowAIOCB),
     .bdrv_write_compressed = qcow_write_compressed,
 
     .bdrv_snapshot_create = qcow_snapshot_create,
index adb3d39..a64564d 100644 (file)
@@ -200,13 +200,13 @@ static int raw_pwrite(BlockDriverState *bs, int64_t offset,
 /* Unix AOP using POSIX AIO */
 
 typedef struct RawAIOCB {
+    BlockDriverAIOCB common;
     struct aiocb aiocb;
-    int busy; /* only used for debugging */
-    BlockDriverAIOCB *next;
+    struct RawAIOCB *next;
 } RawAIOCB;
 
 static int aio_sig_num = SIGUSR2;
-static BlockDriverAIOCB *first_aio; /* AIO issued */
+static RawAIOCB *first_aio; /* AIO issued */
 static int aio_initialized = 0;
 
 static void aio_signal_handler(int signum)
@@ -249,8 +249,7 @@ void qemu_aio_init(void)
 
 void qemu_aio_poll(void)
 {
-    BlockDriverAIOCB *acb, **pacb;
-    RawAIOCB *acb1;
+    RawAIOCB *acb, **pacb;
     int ret;
 
     for(;;) {
@@ -259,17 +258,16 @@ void qemu_aio_poll(void)
             acb = *pacb;
             if (!acb)
                 goto the_end;
-            acb1 = acb->opaque;
-            ret = aio_error(&acb1->aiocb);
+            ret = aio_error(&acb->aiocb);
             if (ret == ECANCELED) {
                 /* remove the request */
-                acb1->busy = 0;
-                *pacb = acb1->next;
+                *pacb = acb->next;
+                qemu_aio_release(acb);
             } else if (ret != EINPROGRESS) {
                 /* end of aio */
                 if (ret == 0) {
-                    ret = aio_return(&acb1->aiocb);
-                    if (ret == acb1->aiocb.aio_nbytes)
+                    ret = aio_return(&acb->aiocb);
+                    if (ret == acb->aiocb.aio_nbytes)
                         ret = 0;
                     else
                         ret = -1;
@@ -277,13 +275,13 @@ void qemu_aio_poll(void)
                     ret = -ret;
                 }
                 /* remove the request */
-                acb1->busy = 0;
-                *pacb = acb1->next;
+                *pacb = acb->next;
                 /* call the callback */
-                acb->cb(acb->cb_opaque, ret);
+                acb->common.cb(acb->common.opaque, ret);
+                qemu_aio_release(acb);
                 break;
             } else {
-                pacb = &acb1->next;
+                pacb = &acb->next;
             }
         }
     }
@@ -324,70 +322,70 @@ void qemu_aio_wait_end(void)
     sigprocmask(SIG_SETMASK, &wait_oset, NULL);
 }
 
-static int raw_aio_new(BlockDriverAIOCB *acb)
+static RawAIOCB *raw_aio_setup(BlockDriverState *bs,
+        int64_t sector_num, uint8_t *buf, int nb_sectors,
+        BlockDriverCompletionFunc *cb, void *opaque)
 {
-    RawAIOCB *acb1;
-    BDRVRawState *s = acb->bs->opaque;
-
-    acb1 = qemu_mallocz(sizeof(RawAIOCB));
-    if (!acb1)
-        return -1;
-    acb->opaque = acb1;
-    acb1->aiocb.aio_fildes = s->fd;
-    acb1->aiocb.aio_sigevent.sigev_signo = aio_sig_num;
-    acb1->aiocb.aio_sigevent.sigev_notify = SIGEV_SIGNAL;
-    return 0;
+    BDRVRawState *s = bs->opaque;
+    RawAIOCB *acb;
+
+    acb = qemu_aio_get(bs, cb, opaque);
+    if (!acb)
+        return NULL;
+    acb->aiocb.aio_fildes = s->fd;
+    acb->aiocb.aio_sigevent.sigev_signo = aio_sig_num;
+    acb->aiocb.aio_sigevent.sigev_notify = SIGEV_SIGNAL;
+    acb->aiocb.aio_buf = buf;
+    acb->aiocb.aio_nbytes = nb_sectors * 512;
+    acb->aiocb.aio_offset = sector_num * 512;
+    acb->next = first_aio;
+    first_aio = acb;
+    return acb;
 }
 
-static int raw_aio_read(BlockDriverAIOCB *acb, int64_t sector_num, 
-                        uint8_t *buf, int nb_sectors)
+static BlockDriverAIOCB *raw_aio_read(BlockDriverState *bs,
+        int64_t sector_num, uint8_t *buf, int nb_sectors,
+        BlockDriverCompletionFunc *cb, void *opaque)
 {
-    RawAIOCB *acb1 = acb->opaque;
+    RawAIOCB *acb;
 
-    assert(acb1->busy == 0);
-    acb1->busy = 1;
-    acb1->aiocb.aio_buf = buf;
-    acb1->aiocb.aio_nbytes = nb_sectors * 512;
-    acb1->aiocb.aio_offset = sector_num * 512;
-    acb1->next = first_aio;
-    first_aio = acb;
-    if (aio_read(&acb1->aiocb) < 0) {
-        acb1->busy = 0;
-        return -errno;
+    acb = raw_aio_setup(bs, sector_num, buf, nb_sectors, cb, opaque);
+    if (!acb)
+        return NULL;
+    if (aio_read(&acb->aiocb) < 0) {
+        qemu_aio_release(acb);
+        return NULL;
     } 
-    return 0;
+    return &acb->common;
 }
 
-static int raw_aio_write(BlockDriverAIOCB *acb, int64_t sector_num, 
-                         const uint8_t *buf, int nb_sectors)
+static BlockDriverAIOCB *raw_aio_write(BlockDriverState *bs,
+        int64_t sector_num, const uint8_t *buf, int nb_sectors,
+        BlockDriverCompletionFunc *cb, void *opaque)
 {
-    RawAIOCB *acb1 = acb->opaque;
+    RawAIOCB *acb;
 
-    assert(acb1->busy == 0);
-    acb1->busy = 1;
-    acb1->aiocb.aio_buf = (uint8_t *)buf;
-    acb1->aiocb.aio_nbytes = nb_sectors * 512;
-    acb1->aiocb.aio_offset = sector_num * 512;
-    acb1->next = first_aio;
-    first_aio = acb;
-    if (aio_write(&acb1->aiocb) < 0) {
-        acb1->busy = 0;
-        return -errno;
+    acb = raw_aio_setup(bs, sector_num, (uint8_t*)buf, nb_sectors, cb, opaque);
+    if (!acb)
+        return NULL;
+    if (aio_write(&acb->aiocb) < 0) {
+        qemu_aio_release(acb);
+        return NULL;
     } 
-    return 0;
+    return &acb->common;
 }
 
-static void raw_aio_cancel(BlockDriverAIOCB *acb)
+static void raw_aio_cancel(BlockDriverAIOCB *blockacb)
 {
-    RawAIOCB *acb1 = acb->opaque;
     int ret;
-    BlockDriverAIOCB **pacb;
+    RawAIOCB *acb = (RawAIOCB *)blockacb;
+    RawAIOCB **pacb;
 
-    ret = aio_cancel(acb1->aiocb.aio_fildes, &acb1->aiocb);
+    ret = aio_cancel(acb->aiocb.aio_fildes, &acb->aiocb);
     if (ret == AIO_NOTCANCELED) {
         /* fail safe: if the aio could not be canceled, we wait for
            it */
-        while (aio_error(&acb1->aiocb) == EINPROGRESS);
+        while (aio_error(&acb->aiocb) == EINPROGRESS);
     }
 
     /* remove the callback from the queue */
@@ -396,22 +394,14 @@ static void raw_aio_cancel(BlockDriverAIOCB *acb)
         if (*pacb == NULL) {
             break;
         } else if (*pacb == acb) {
-            acb1->busy = 0;
-            *pacb = acb1->next;
+            *pacb = acb->next;
+            qemu_aio_release(acb);
             break;
         }
-        acb1 = (*pacb)->opaque;
-        pacb = &acb1->next;
+        pacb = &acb->next;
     }
 }
 
-static void raw_aio_delete(BlockDriverAIOCB *acb)
-{
-    RawAIOCB *acb1 = acb->opaque;
-    raw_aio_cancel(acb);
-    qemu_free(acb1);
-}
-
 static void raw_close(BlockDriverState *bs)
 {
     BDRVRawState *s = bs->opaque;
@@ -508,11 +498,10 @@ BlockDriver bdrv_raw = {
     raw_create,
     raw_flush,
     
-    .bdrv_aio_new = raw_aio_new,
     .bdrv_aio_read = raw_aio_read,
     .bdrv_aio_write = raw_aio_write,
     .bdrv_aio_cancel = raw_aio_cancel,
-    .bdrv_aio_delete = raw_aio_delete,
+    .aiocb_size = sizeof(RawAIOCB),
     .protocol_name = "file",
     .bdrv_pread = raw_pread,
     .bdrv_pwrite = raw_pwrite,
@@ -530,6 +519,7 @@ typedef struct BDRVRawState {
 } BDRVRawState;
 
 typedef struct RawAIOCB {
+    BlockDriverAIOCB common;
     HANDLE hEvent;
     OVERLAPPED ov;
     int count;
@@ -574,6 +564,7 @@ static int raw_open(BlockDriverState *bs, const char *filename, int flags)
 {
     BDRVRawState *s = bs->opaque;
     int access_flags, create_flags;
+    DWORD overlapped;
 
     if ((flags & BDRV_O_ACCESS) == O_RDWR) {
         access_flags = GENERIC_READ | GENERIC_WRITE;
@@ -585,9 +576,14 @@ static int raw_open(BlockDriverState *bs, const char *filename, int flags)
     } else {
         create_flags = OPEN_EXISTING;
     }
+#ifdef QEMU_TOOL
+    overlapped = 0;
+#else
+    overlapped = FILE_FLAG_OVERLAPPED;
+#endif
     s->hfile = CreateFile(filename, access_flags, 
                           FILE_SHARE_READ, NULL,
-                          create_flags, FILE_FLAG_OVERLAPPED, 0);
+                          create_flags, overlapped, 0);
     if (s->hfile == INVALID_HANDLE_VALUE) 
         return -1;
     return 0;
@@ -637,104 +633,107 @@ static int raw_pwrite(BlockDriverState *bs, int64_t offset,
     return ret_count;
 }
 
-static int raw_aio_new(BlockDriverAIOCB *acb)
-{
-    RawAIOCB *acb1;
-
-    acb1 = qemu_mallocz(sizeof(RawAIOCB));
-    if (!acb1)
-        return -ENOMEM;
-    acb->opaque = acb1;
-    acb1->hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
-    if (!acb1->hEvent)
-        return -ENOMEM;
-    return 0;
-}
 #ifndef QEMU_TOOL
 static void raw_aio_cb(void *opaque)
 {
-    BlockDriverAIOCB *acb = opaque;
-    BlockDriverState *bs = acb->bs;
+    RawAIOCB *acb = opaque;
+    BlockDriverState *bs = acb->common.bs;
     BDRVRawState *s = bs->opaque;
-    RawAIOCB *acb1 = acb->opaque;
     DWORD ret_count;
     int ret;
 
-    ret = GetOverlappedResult(s->hfile, &acb1->ov, &ret_count, TRUE);
-    if (!ret || ret_count != acb1->count) {
-        acb->cb(acb->cb_opaque, -EIO);
+    ret = GetOverlappedResult(s->hfile, &acb->ov, &ret_count, TRUE);
+    if (!ret || ret_count != acb->count) {
+        acb->common.cb(acb->common.opaque, -EIO);
     } else {
-        acb->cb(acb->cb_opaque, 0);
+        acb->common.cb(acb->common.opaque, 0);
     }
 }
 #endif
-static int raw_aio_read(BlockDriverAIOCB *acb, int64_t sector_num, 
-                        uint8_t *buf, int nb_sectors)
+
+static RawAIOCB *raw_aio_setup(BlockDriverState *bs,
+        int64_t sector_num, uint8_t *buf, int nb_sectors,
+        BlockDriverCompletionFunc *cb, void *opaque)
 {
-    BlockDriverState *bs = acb->bs;
-    BDRVRawState *s = bs->opaque;
-    RawAIOCB *acb1 = acb->opaque;
-    int ret;
+    RawAIOCB *acb;
     int64_t offset;
 
-    memset(&acb1->ov, 0, sizeof(acb1->ov));
+    acb = qemu_aio_get(bs, cb, opaque);
+    if (acb->hEvent) {
+        acb->hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+        if (!acb->hEvent) {
+            qemu_aio_release(acb);
+            return NULL;
+        }
+    }
+    memset(&acb->ov, 0, sizeof(acb->ov));
     offset = sector_num * 512;
-    acb1->ov.Offset = offset;
-    acb1->ov.OffsetHigh = offset >> 32;
-    acb1->ov.hEvent = acb1->hEvent;
-    acb1->count = nb_sectors * 512;
+    acb->ov.Offset = offset;
+    acb->ov.OffsetHigh = offset >> 32;
+    acb->ov.hEvent = acb->hEvent;
+    acb->count = nb_sectors * 512;
 #ifndef QEMU_TOOL
-    qemu_add_wait_object(acb1->ov.hEvent, raw_aio_cb, acb);
+    qemu_add_wait_object(acb->ov.hEvent, raw_aio_cb, acb);
 #endif
-    ret = ReadFile(s->hfile, buf, acb1->count, NULL, &acb1->ov);
-    if (!ret)
-        return -EIO;
-    return 0;
+    return acb;
 }
 
-static int raw_aio_write(BlockDriverAIOCB *acb, int64_t sector_num, 
-                         uint8_t *buf, int nb_sectors)
+static BlockDriverAIOCB *raw_aio_read(BlockDriverState *bs,
+        int64_t sector_num, uint8_t *buf, int nb_sectors,
+        BlockDriverCompletionFunc *cb, void *opaque)
 {
-    BlockDriverState *bs = acb->bs;
     BDRVRawState *s = bs->opaque;
-    RawAIOCB *acb1 = acb->opaque;
+    RawAIOCB *acb;
     int ret;
-    int64_t offset;
 
-    memset(&acb1->ov, 0, sizeof(acb1->ov));
-    offset = sector_num * 512;
-    acb1->ov.Offset = offset;
-    acb1->ov.OffsetHigh = offset >> 32;
-    acb1->ov.hEvent = acb1->hEvent;
-    acb1->count = nb_sectors * 512;
-#ifndef QEMU_TOOL
-    qemu_add_wait_object(acb1->ov.hEvent, raw_aio_cb, acb);
+    acb = raw_aio_setup(bs, sector_num, buf, nb_sectors, cb, opaque);
+    if (!acb)
+        return NULL;
+    ret = ReadFile(s->hfile, buf, acb->count, NULL, &acb->ov);
+    if (!ret) {
+        qemu_aio_release(acb);
+        return NULL;
+    }
+#ifdef QEMU_TOOL
+    qemu_aio_release(acb);
 #endif
-    ret = ReadFile(s->hfile, buf, acb1->count, NULL, &acb1->ov);
-    if (!ret)
-        return -EIO;
-    return 0;
+    return (BlockDriverAIOCB *)acb;
 }
 
-static void raw_aio_cancel(BlockDriverAIOCB *acb)
+static BlockDriverAIOCB *raw_aio_write(BlockDriverState *bs,
+        int64_t sector_num, uint8_t *buf, int nb_sectors,
+        BlockDriverCompletionFunc *cb, void *opaque)
 {
-    BlockDriverState *bs = acb->bs;
     BDRVRawState *s = bs->opaque;
-#ifndef QEMU_TOOL
-    RawAIOCB *acb1 = acb->opaque;
+    RawAIOCB *acb;
+    int ret;
 
-    qemu_del_wait_object(acb1->ov.hEvent, raw_aio_cb, acb);
+    acb = raw_aio_setup(bs, sector_num, buf, nb_sectors, cb, opaque);
+    if (!acb)
+        return NULL;
+    ret = WriteFile(s->hfile, buf, acb->count, NULL, &acb->ov);
+    if (!ret) {
+        qemu_aio_release(acb);
+        return NULL;
+    }
+#ifdef QEMU_TOOL
+    qemu_aio_release(acb);
 #endif
-    /* XXX: if more than one async I/O it is not correct */
-    CancelIo(s->hfile);
+    return (BlockDriverAIOCB *)acb;
 }
 
-static void raw_aio_delete(BlockDriverAIOCB *acb)
+static void raw_aio_cancel(BlockDriverAIOCB *blockacb)
 {
-    RawAIOCB *acb1 = acb->opaque;
-    raw_aio_cancel(acb);
-    CloseHandle(acb1->hEvent);
-    qemu_free(acb1);
+#ifndef QEMU_TOOL
+    RawAIOCB *acb = (RawAIOCB *)blockacb;
+    BlockDriverState *bs = acb->common.bs;
+    BDRVRawState *s = bs->opaque;
+
+    qemu_del_wait_object(acb->ov.hEvent, raw_aio_cb, acb);
+    /* XXX: if more than one async I/O it is not correct */
+    CancelIo(s->hfile);
+    qemu_aio_release(acb);
+#endif
 }
 
 static void raw_flush(BlockDriverState *bs)
@@ -823,11 +822,10 @@ BlockDriver bdrv_raw = {
     raw_flush,
     
 #if 0
-    .bdrv_aio_new = raw_aio_new,
     .bdrv_aio_read = raw_aio_read,
     .bdrv_aio_write = raw_aio_write,
     .bdrv_aio_cancel = raw_aio_cancel,
-    .bdrv_aio_delete = raw_aio_delete,
+    .aiocb_size = sizeof(RawAIOCB);
 #endif
     .protocol_name = "file",
     .bdrv_pread = raw_pread,
diff --git a/block.c b/block.c
index dacee2f..0c2fc6e 100644 (file)
--- a/block.c
+++ b/block.c
 #define SECTOR_BITS 9
 #define SECTOR_SIZE (1 << SECTOR_BITS)
 
-static int bdrv_aio_new_em(BlockDriverAIOCB *acb);
-static int bdrv_aio_read_em(BlockDriverAIOCB *acb, int64_t sector_num,
-                              uint8_t *buf, int nb_sectors);
-static int bdrv_aio_write_em(BlockDriverAIOCB *acb, int64_t sector_num,
-                               const uint8_t *buf, int nb_sectors);
+static BlockDriverAIOCB *bdrv_aio_read_em(BlockDriverState *bs,
+        int64_t sector_num, uint8_t *buf, int nb_sectors,
+        BlockDriverCompletionFunc *cb, void *opaque);
+static BlockDriverAIOCB *bdrv_aio_write_em(BlockDriverState *bs,
+        int64_t sector_num, const uint8_t *buf, int nb_sectors,
+        BlockDriverCompletionFunc *cb, void *opaque);
 static void bdrv_aio_cancel_em(BlockDriverAIOCB *acb);
-static void bdrv_aio_delete_em(BlockDriverAIOCB *acb);
 static int bdrv_read_em(BlockDriverState *bs, int64_t sector_num, 
                         uint8_t *buf, int nb_sectors);
 static int bdrv_write_em(BlockDriverState *bs, int64_t sector_num,
@@ -106,13 +106,11 @@ void path_combine(char *dest, int dest_size,
 
 void bdrv_register(BlockDriver *bdrv)
 {
-    if (!bdrv->bdrv_aio_new) {
+    if (!bdrv->bdrv_aio_read) {
         /* add AIO emulation layer */
-        bdrv->bdrv_aio_new = bdrv_aio_new_em;
         bdrv->bdrv_aio_read = bdrv_aio_read_em;
         bdrv->bdrv_aio_write = bdrv_aio_write_em;
         bdrv->bdrv_aio_cancel = bdrv_aio_cancel_em;
-        bdrv->bdrv_aio_delete = bdrv_aio_delete_em;
     } else if (!bdrv->bdrv_read && !bdrv->bdrv_pread) {
         /* add synchronous IO emulation layer */
         bdrv->bdrv_read = bdrv_read_em;
@@ -964,7 +962,9 @@ char *bdrv_snapshot_dump(char *buf, int buf_size, QEMUSnapshotInfo *sn)
                  "ID", "TAG", "VM SIZE", "DATE", "VM CLOCK");
     } else {
         ti = sn->date_sec;
+#ifndef _WIN32
         localtime_r(&ti, &tm);
+#endif
         strftime(date_buf, sizeof(date_buf),
                  "%Y-%m-%d %H:%M:%S", &tm);
         secs = sn->vm_clock_nsec / 1000000000;
@@ -988,31 +988,14 @@ char *bdrv_snapshot_dump(char *buf, int buf_size, QEMUSnapshotInfo *sn)
 /**************************************************************/
 /* async I/Os */
 
-BlockDriverAIOCB *bdrv_aio_new(BlockDriverState *bs)
+BlockDriverAIOCB *bdrv_aio_read(BlockDriverState *bs, int64_t sector_num,
+                                uint8_t *buf, int nb_sectors,
+                                BlockDriverCompletionFunc *cb, void *opaque)
 {
     BlockDriver *drv = bs->drv;
-    BlockDriverAIOCB *acb;
-    acb = qemu_mallocz(sizeof(BlockDriverAIOCB));
-    if (!acb)
-        return NULL;
-    
-    acb->bs = bs;
-    if (drv->bdrv_aio_new(acb) < 0) {
-        qemu_free(acb);
-        return NULL;
-    }
-    return acb;
-}
-
-int bdrv_aio_read(BlockDriverAIOCB *acb, int64_t sector_num,
-                  uint8_t *buf, int nb_sectors,
-                  BlockDriverCompletionFunc *cb, void *opaque)
-{
-    BlockDriverState *bs = acb->bs;
-    BlockDriver *drv = bs->drv;
 
     if (!bs->inserted)
-        return -1;
+        return NULL;
     
     /* XXX: we assume that nb_sectors == 0 is suppored by the async read */
     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,
         buf += 512;
     }
 
-    acb->cb = cb;
-    acb->cb_opaque = opaque;
-    return drv->bdrv_aio_read(acb, sector_num, buf, nb_sectors);
+    return drv->bdrv_aio_read(bs, sector_num, buf, nb_sectors, cb, opaque);
 }
 
-int bdrv_aio_write(BlockDriverAIOCB *acb, int64_t sector_num,
-                   const uint8_t *buf, int nb_sectors,
-                   BlockDriverCompletionFunc *cb, void *opaque)
+BlockDriverAIOCB *bdrv_aio_write(BlockDriverState *bs, int64_t sector_num,
+                                 const uint8_t *buf, int nb_sectors,
+                                 BlockDriverCompletionFunc *cb, void *opaque)
 {
-    BlockDriverState *bs = acb->bs;
     BlockDriver *drv = bs->drv;
 
     if (!bs->inserted)
-            return -1;
+        return NULL;
     if (bs->read_only)
-        return -1;
+        return NULL;
     if (sector_num == 0 && bs->boot_sector_enabled && nb_sectors > 0) {
         memcpy(bs->boot_sector_data, buf, 512);   
     }
 
-    acb->cb = cb;
-    acb->cb_opaque = opaque;
-    return drv->bdrv_aio_write(acb, sector_num, buf, nb_sectors);
+    return drv->bdrv_aio_write(bs, sector_num, buf, nb_sectors, cb, opaque);
 }
 
 void bdrv_aio_cancel(BlockDriverAIOCB *acb)
-    {
-    BlockDriverState *bs = acb->bs;
-    BlockDriver *drv = bs->drv;
-
-    drv->bdrv_aio_cancel(acb);
-    }
-
-void bdrv_aio_delete(BlockDriverAIOCB *acb)
 {
-    BlockDriverState *bs = acb->bs;
-    BlockDriver *drv = bs->drv;
+    BlockDriver *drv = acb->bs->drv;
 
-    drv->bdrv_aio_delete(acb);
-    qemu_free(acb);
+    drv->bdrv_aio_cancel(acb);
 }
 
+
 /**************************************************************/
 /* async block device emulation */
 
 #ifdef QEMU_TOOL
-static int bdrv_aio_new_em(BlockDriverAIOCB *acb)
-{
-    return 0;
-}
-
-static int bdrv_aio_read_em(BlockDriverAIOCB *acb, int64_t sector_num,
-                    uint8_t *buf, int nb_sectors)
+static BlockDriverAIOCB *bdrv_aio_read_em(BlockDriverState *bs,
+        int64_t sector_num, uint8_t *buf, int nb_sectors,
+        BlockDriverCompletionFunc *cb, void *opaque)
 {
     int ret;
-    ret = bdrv_read(acb->bs, sector_num, buf, nb_sectors);
-    acb->cb(acb->cb_opaque, ret);
-    return 0;
+    ret = bdrv_read(bs, sector_num, buf, nb_sectors);
+    cb(opaque, ret);
+    return NULL;
 }
 
-static int bdrv_aio_write_em(BlockDriverAIOCB *acb, int64_t sector_num,
-                     const uint8_t *buf, int nb_sectors)
+static BlockDriverAIOCB *bdrv_aio_write_em(BlockDriverState *bs,
+        int64_t sector_num, const uint8_t *buf, int nb_sectors,
+        BlockDriverCompletionFunc *cb, void *opaque)
 {
     int ret;
-    ret = bdrv_write(acb->bs, sector_num, buf, nb_sectors);
-    acb->cb(acb->cb_opaque, ret);
-    return 0;
+    ret = bdrv_write(bs, sector_num, buf, nb_sectors);
+    cb(opaque, ret);
+    return NULL;
 }
 
 static void bdrv_aio_cancel_em(BlockDriverAIOCB *acb)
 {
 }
-
-static void bdrv_aio_delete_em(BlockDriverAIOCB *acb)
-{
-}
 #else
 typedef struct BlockDriverAIOCBSync {
+    BlockDriverAIOCB common;
     QEMUBH *bh;
     int ret;
 } BlockDriverAIOCBSync;
 
-static void bdrv_aio_bh_cb(void *opaque)
-{
-    BlockDriverAIOCB *acb = opaque;
-    BlockDriverAIOCBSync *acb1 = acb->opaque;
-    acb->cb(acb->cb_opaque, acb1->ret);
-}
+static BlockDriverAIOCBSync *free_acb = NULL;
 
-static int bdrv_aio_new_em(BlockDriverAIOCB *acb)
+static void bdrv_aio_bh_cb(void *opaque)
 {
-    BlockDriverAIOCBSync *acb1;
-
-    acb1 = qemu_mallocz(sizeof(BlockDriverAIOCBSync));
-    if (!acb1)
-        return -1;
-    acb->opaque = acb1;
-    acb1->bh = qemu_bh_new(bdrv_aio_bh_cb, acb);
-    return 0;
+    BlockDriverAIOCBSync *acb = opaque;
+    acb->common.cb(acb->common.opaque, acb->ret);
+    qemu_aio_release(acb);
 }
 
-static int bdrv_aio_read_em(BlockDriverAIOCB *acb, int64_t sector_num,
-                    uint8_t *buf, int nb_sectors)
+static BlockDriverAIOCB *bdrv_aio_read_em(BlockDriverState *bs,
+        int64_t sector_num, uint8_t *buf, int nb_sectors,
+        BlockDriverCompletionFunc *cb, void *opaque)
 {
-    BlockDriverAIOCBSync *acb1 = acb->opaque;
+    BlockDriverAIOCBSync *acb;
     int ret;
-    
-    ret = bdrv_read(acb->bs, sector_num, buf, nb_sectors);
-    acb1->ret = ret;
-    qemu_bh_schedule(acb1->bh);
-    return 0;
+
+    acb = qemu_aio_get(bs, cb, opaque);
+    if (!acb->bh)
+        acb->bh = qemu_bh_new(bdrv_aio_bh_cb, acb);
+    ret = bdrv_read(bs, sector_num, buf, nb_sectors);
+    acb->ret = ret;
+    qemu_bh_schedule(acb->bh);
+    return &acb->common;
 }
 
-static int bdrv_aio_write_em(BlockDriverAIOCB *acb, int64_t sector_num,
-                     const uint8_t *buf, int nb_sectors)
+static BlockDriverAIOCB *bdrv_aio_write_em(BlockDriverState *bs,
+        int64_t sector_num, const uint8_t *buf, int nb_sectors,
+        BlockDriverCompletionFunc *cb, void *opaque)
 {
-    BlockDriverAIOCBSync *acb1 = acb->opaque;
+    BlockDriverAIOCBSync *acb;
     int ret;
-    
-    ret = bdrv_write(acb->bs, sector_num, buf, nb_sectors);
-    acb1->ret = ret;
-    qemu_bh_schedule(acb1->bh);
-    return 0;
-}
 
-static void bdrv_aio_cancel_em(BlockDriverAIOCB *acb)
-{
-    BlockDriverAIOCBSync *acb1 = acb->opaque;
-    qemu_bh_cancel(acb1->bh);
+    acb = qemu_aio_get(bs, cb, opaque);
+    if (!acb->bh)
+        acb->bh = qemu_bh_new(bdrv_aio_bh_cb, acb);
+    ret = bdrv_write(bs, sector_num, buf, nb_sectors);
+    acb->ret = ret;
+    qemu_bh_schedule(acb->bh);
+    return &acb->common;
 }
 
-static void bdrv_aio_delete_em(BlockDriverAIOCB *acb)
+static void bdrv_aio_cancel_em(BlockDriverAIOCB *blockacb)
 {
-    BlockDriverAIOCBSync *acb1 = acb->opaque;
-    qemu_bh_delete(acb1->bh);
+    BlockDriverAIOCBSync *acb = (BlockDriverAIOCBSync *)blockacb;
+    qemu_bh_cancel(acb->bh);
+    qemu_aio_release(acb);
 }
 #endif /* !QEMU_TOOL */
 
@@ -1173,20 +1129,16 @@ static void bdrv_rw_em_cb(void *opaque, int ret)
 static int bdrv_read_em(BlockDriverState *bs, int64_t sector_num, 
                         uint8_t *buf, int nb_sectors)
 {
-    int async_ret, ret;
+    int async_ret;
+    BlockDriverAIOCB *acb;
 
-    if (!bs->sync_aiocb) {
-        bs->sync_aiocb = bdrv_aio_new(bs);
-        if (!bs->sync_aiocb)
-            return -1;
-    }
     async_ret = NOT_DONE;
     qemu_aio_wait_start();
-    ret = bdrv_aio_read(bs->sync_aiocb, sector_num, buf, nb_sectors, 
+    acb = bdrv_aio_read(bs, sector_num, buf, nb_sectors, 
                         bdrv_rw_em_cb, &async_ret);
-    if (ret < 0) {
+    if (acb == NULL) {
         qemu_aio_wait_end();
-        return ret;
+        return -1;
     }
     while (async_ret == NOT_DONE) {
         qemu_aio_wait();
@@ -1198,20 +1150,16 @@ static int bdrv_read_em(BlockDriverState *bs, int64_t sector_num,
 static int bdrv_write_em(BlockDriverState *bs, int64_t sector_num,
                          const uint8_t *buf, int nb_sectors)
 {
-    int async_ret, ret;
+    int async_ret;
+    BlockDriverAIOCB *acb;
 
-    if (!bs->sync_aiocb) {
-        bs->sync_aiocb = bdrv_aio_new(bs);
-        if (!bs->sync_aiocb)
-            return -1;
-    }
     async_ret = NOT_DONE;
     qemu_aio_wait_start();
-    ret = bdrv_aio_write(bs->sync_aiocb, sector_num, buf, nb_sectors, 
+    acb = bdrv_aio_write(bs, sector_num, buf, nb_sectors, 
                          bdrv_rw_em_cb, &async_ret);
-    if (ret < 0) {
+    if (acb == NULL) {
         qemu_aio_wait_end();
-        return ret;
+        return -1;
     }
     while (async_ret == NOT_DONE) {
         qemu_aio_wait();
@@ -1235,3 +1183,32 @@ void bdrv_init(void)
     bdrv_register(&bdrv_vvfat);
     bdrv_register(&bdrv_qcow2);
 }
+
+void *qemu_aio_get(BlockDriverState *bs, BlockDriverCompletionFunc *cb,
+                   void *opaque)
+{
+    BlockDriver *drv;
+    BlockDriverAIOCB *acb;
+
+    drv = bs->drv;
+    if (drv->free_aiocb) {
+        acb = drv->free_aiocb;
+        drv->free_aiocb = acb->next;
+    } else {
+        acb = qemu_mallocz(drv->aiocb_size);
+        if (!acb)
+            return NULL;
+    }
+    acb->bs = bs;
+    acb->cb = cb;
+    acb->opaque = opaque;
+    return acb;
+}
+
+void qemu_aio_release(void *p)
+{
+    BlockDriverAIOCB *acb = p;
+    BlockDriver *drv = acb->bs->drv;
+    acb->next = drv->free_aiocb;
+    drv->free_aiocb = acb;
+}
index 26cc4ff..8fd241f 100644 (file)
@@ -42,13 +42,14 @@ struct BlockDriver {
     int (*bdrv_set_key)(BlockDriverState *bs, const char *key);
     int (*bdrv_make_empty)(BlockDriverState *bs);
     /* aio */
-    int (*bdrv_aio_new)(BlockDriverAIOCB *acb);
-    int (*bdrv_aio_read)(BlockDriverAIOCB *acb, int64_t sector_num,
-                              uint8_t *buf, int nb_sectors);
-    int (*bdrv_aio_write)(BlockDriverAIOCB *acb, int64_t sector_num,
-                          const uint8_t *buf, int nb_sectors);
+    BlockDriverAIOCB *(*bdrv_aio_read)(BlockDriverState *bs,
+        int64_t sector_num, uint8_t *buf, int nb_sectors,
+        BlockDriverCompletionFunc *cb, void *opaque);
+    BlockDriverAIOCB *(*bdrv_aio_write)(BlockDriverState *bs,
+        int64_t sector_num, const uint8_t *buf, int nb_sectors,
+        BlockDriverCompletionFunc *cb, void *opaque);
     void (*bdrv_aio_cancel)(BlockDriverAIOCB *acb);
-    void (*bdrv_aio_delete)(BlockDriverAIOCB *acb);
+    int aiocb_size;
 
     const char *protocol_name;
     int (*bdrv_pread)(BlockDriverState *bs, int64_t offset, 
@@ -69,6 +70,7 @@ struct BlockDriver {
                               QEMUSnapshotInfo **psn_info);
     int (*bdrv_get_info)(BlockDriverState *bs, BlockDriverInfo *bdi);
 
+    BlockDriverAIOCB *free_aiocb;
     struct BlockDriver *next;
 };
 
@@ -96,9 +98,9 @@ struct BlockDriverState {
     int is_temporary;
     
     BlockDriverState *backing_hd;
-    /* sync read/write emulation */
+    /* async read/write emulation */
 
-    BlockDriverAIOCB *sync_aiocb;
+    void *sync_aiocb;
     
     /* NOTE: the following infos are only hints for real hardware
        drivers. They are not used by the block driver */
@@ -111,11 +113,14 @@ struct BlockDriverState {
 struct BlockDriverAIOCB {
     BlockDriverState *bs;
     BlockDriverCompletionFunc *cb;
-    void *cb_opaque;
-    
-    void *opaque; /* driver opaque */
+    void *opaque;
+    BlockDriverAIOCB *next;
 };
 
 void get_tmp_filename(char *filename, int size);
 
+void *qemu_aio_get(BlockDriverState *bs, BlockDriverCompletionFunc *cb,
+                   void *opaque);
+void qemu_aio_release(void *p);
+
 #endif /* BLOCK_INT_H */
diff --git a/vl.h b/vl.h
index ce52fb8..1632e35 100644 (file)
--- a/vl.h
+++ b/vl.h
@@ -569,15 +569,13 @@ void bdrv_set_boot_sector(BlockDriverState *bs, const uint8_t *data, int size);
 typedef struct BlockDriverAIOCB BlockDriverAIOCB;
 typedef void BlockDriverCompletionFunc(void *opaque, int ret);
 
-BlockDriverAIOCB *bdrv_aio_new(BlockDriverState *bs);
-int bdrv_aio_read(BlockDriverAIOCB *acb, int64_t sector_num,
-                  uint8_t *buf, int nb_sectors,
-                  BlockDriverCompletionFunc *cb, void *opaque);
-int bdrv_aio_write(BlockDriverAIOCB *acb, int64_t sector_num,
-                   const uint8_t *buf, int nb_sectors,
-                   BlockDriverCompletionFunc *cb, void *opaque);
+BlockDriverAIOCB *bdrv_aio_read(BlockDriverState *bs, int64_t sector_num,
+                                uint8_t *buf, int nb_sectors,
+                                BlockDriverCompletionFunc *cb, void *opaque);
+BlockDriverAIOCB *bdrv_aio_write(BlockDriverState *bs, int64_t sector_num,
+                                 const uint8_t *buf, int nb_sectors,
+                                 BlockDriverCompletionFunc *cb, void *opaque);
 void bdrv_aio_cancel(BlockDriverAIOCB *acb);
-void bdrv_aio_delete(BlockDriverAIOCB *acb);
 
 void qemu_aio_init(void);
 void qemu_aio_poll(void);