Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > media > main-src > by-pkgid > aadbe78a25743146bb784eee19f007c5 > files > 236

kvm-83-164.el5_5.9.src.rpm

From 9a3edf82a956d1c60c24491d368ca423de84ed92 Mon Sep 17 00:00:00 2001
From: Christoph Hellwig <chellwig@redhat.com>
Date: Tue, 24 Nov 2009 19:43:07 -0200
Subject: [PATCH 02/11] block: add aio_flush operation

RH-Author: Christoph Hellwig <chellwig@redhat.com>
Message-id: <1256889826.9905.4.camel@brick.lst.de>
Patchwork-id: 3654
O-Subject: [PATCH 3/5] block: add aio_flush operation
Bugzilla: 537646
RH-Acked-by: Rik van Riel <riel@redhat.com>
RH-Acked-by: Kevin Wolf <kwolf@redhat.com>
RH-Acked-by: Juan Quintela <quintela@redhat.com>

commit b2e12bc6e304c17da0bee970fb4776d0731422e6
Author: Christoph Hellwig <hch@lst.de>
Date:   Fri Sep 4 19:01:49 2009 +0200

    block: add aio_flush operation

    Instead stalling the VCPU while serving a cache flush try to do it
    asynchronously.  Use our good old helper thread pool to issue an
    asynchronous fdatasync for raw-posix.  Note that while Linux AIO
    implements a fdatasync operation it is not useful for us because
    it isn't actually implement in asynchronous fashion.

    Signed-off-by: Christoph Hellwig <hch@lst.de>
    Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>

Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
---
 qemu/block-raw-posix.c  |   21 ++++++++++++++++++++-
 qemu/block.c            |   37 +++++++++++++++++++++++++++++++++++++
 qemu/block.h            |    2 ++
 qemu/block_int.h        |    2 ++
 qemu/posix-aio-compat.c |   31 +++++++++++++++++++++++++------
 qemu/posix-aio-compat.h |    3 ++-
 6 files changed, 88 insertions(+), 8 deletions(-)

diff --git a/qemu/block-raw-posix.c b/qemu/block-raw-posix.c
index 52ad357..1e46e03 100644
--- a/qemu/block-raw-posix.c
+++ b/qemu/block-raw-posix.c
@@ -663,6 +663,24 @@ static BlockDriverAIOCB *raw_aio_write(BlockDriverState *bs,
     return &acb->common;
 }
 
+static BlockDriverAIOCB *raw_aio_flush(BlockDriverState *bs,
+        BlockDriverCompletionFunc *cb, void *opaque)
+{
+    RawAIOCB *acb;
+
+    if (fd_open(bs) < 0)
+        return NULL;
+
+    acb = raw_aio_setup(bs, 0, NULL, 0, cb, opaque);
+    if (!acb)
+        return NULL;
+    if (qemu_paio_flush(&acb->aiocb) < 0) {
+        qemu_aio_release(acb);
+        return NULL;
+    }
+    return &acb->common;
+}
+
 static void raw_aio_cancel(BlockDriverAIOCB *blockacb)
 {
     int ret;
@@ -696,7 +714,6 @@ static int posix_aio_init(void)
 }
 #endif /* CONFIG_AIO */
 
-
 static void raw_close(BlockDriverState *bs)
 {
     BDRVRawState *s = bs->opaque;
@@ -830,6 +847,7 @@ BlockDriver bdrv_raw = {
 #ifdef CONFIG_AIO
     .bdrv_aio_read = raw_aio_read,
     .bdrv_aio_write = raw_aio_write,
+    .bdrv_aio_flush = raw_aio_flush,
     .bdrv_aio_cancel = raw_aio_cancel,
     .aiocb_size = sizeof(RawAIOCB),
 #endif
@@ -1224,6 +1242,7 @@ BlockDriver bdrv_host_device = {
 #ifdef CONFIG_AIO
     .bdrv_aio_read = raw_aio_read,
     .bdrv_aio_write = raw_aio_write,
+    .bdrv_aio_flush = raw_aio_flush,
     .bdrv_aio_cancel = raw_aio_cancel,
     .aiocb_size = sizeof(RawAIOCB),
 #endif
diff --git a/qemu/block.c b/qemu/block.c
index 5967748..4f8b295 100644
--- a/qemu/block.c
+++ b/qemu/block.c
@@ -54,6 +54,8 @@ static BlockDriverAIOCB *bdrv_aio_read_em(BlockDriverState *bs,
 static BlockDriverAIOCB *bdrv_aio_write_em(BlockDriverState *bs,
         int64_t sector_num, const uint8_t *buf, int nb_sectors,
         BlockDriverCompletionFunc *cb, void *opaque);
+static BlockDriverAIOCB *bdrv_aio_flush_em(BlockDriverState *bs,
+        BlockDriverCompletionFunc *cb, void *opaque);
 static void bdrv_aio_cancel_em(BlockDriverAIOCB *acb);
 static int bdrv_read_em(BlockDriverState *bs, int64_t sector_num,
                         uint8_t *buf, int nb_sectors);
@@ -144,6 +146,10 @@ static void bdrv_register(BlockDriver *bdrv)
         bdrv->bdrv_read = bdrv_read_em;
         bdrv->bdrv_write = bdrv_write_em;
     }
+
+   if (!bdrv->bdrv_aio_flush)
+       bdrv->bdrv_aio_flush = bdrv_aio_flush_em;
+
     bdrv->next = first_drv;
     first_drv = bdrv;
 }
@@ -1451,6 +1457,21 @@ BlockDriverAIOCB *bdrv_aio_write(BlockDriverState *bs, int64_t sector_num,
     return ret;
 }
 
+BlockDriverAIOCB *bdrv_aio_flush(BlockDriverState *bs,
+        BlockDriverCompletionFunc *cb, void *opaque)
+{
+    BlockDriver *drv = bs->drv;
+
+    if (!drv)
+        return NULL;
+
+    /*
+     * Note that unlike bdrv_flush the driver is reponsible for flushing a
+     * backing image if it exists.
+     */
+    return drv->bdrv_aio_flush(bs, cb, opaque);
+}
+
 void bdrv_aio_cancel(BlockDriverAIOCB *acb)
 {
     BlockDriver *drv = acb->bs->drv;
@@ -1501,6 +1522,22 @@ static BlockDriverAIOCB *bdrv_aio_write_em(BlockDriverState *bs,
     return &acb->common;
 }
 
+static BlockDriverAIOCB *bdrv_aio_flush_em(BlockDriverState *bs,
+        BlockDriverCompletionFunc *cb, void *opaque)
+{
+    BlockDriverAIOCBSync *acb;
+
+    acb = qemu_aio_get(bs, cb, opaque);
+    acb->ret = 0;
+
+    if (!acb->bh)
+        acb->bh = qemu_bh_new(bdrv_aio_bh_cb, acb);
+
+    bdrv_flush(bs);
+    qemu_bh_schedule(acb->bh);
+    return &acb->common;
+}
+
 static void bdrv_aio_cancel_em(BlockDriverAIOCB *blockacb)
 {
     BlockDriverAIOCBSync *acb = (BlockDriverAIOCBSync *)blockacb;
diff --git a/qemu/block.h b/qemu/block.h
index 662082a..cab9cba 100644
--- a/qemu/block.h
+++ b/qemu/block.h
@@ -95,6 +95,8 @@ BlockDriverAIOCB *bdrv_aio_read(BlockDriverState *bs, int64_t sector_num,
 BlockDriverAIOCB *bdrv_aio_write(BlockDriverState *bs, int64_t sector_num,
                                  const uint8_t *buf, int nb_sectors,
                                  BlockDriverCompletionFunc *cb, void *opaque);
+BlockDriverAIOCB *bdrv_aio_flush(BlockDriverState *bs,
+				 BlockDriverCompletionFunc *cb, void *opaque);
 void bdrv_aio_cancel(BlockDriverAIOCB *acb);
 
 int qemu_key_check(BlockDriverState *bs, const char *name);
diff --git a/qemu/block_int.h b/qemu/block_int.h
index 1f77cf0..5334904 100644
--- a/qemu/block_int.h
+++ b/qemu/block_int.h
@@ -54,6 +54,8 @@ struct BlockDriver {
     BlockDriverAIOCB *(*bdrv_aio_write)(BlockDriverState *bs,
         int64_t sector_num, const uint8_t *buf, int nb_sectors,
         BlockDriverCompletionFunc *cb, void *opaque);
+    BlockDriverAIOCB *(*bdrv_aio_flush)(BlockDriverState *bs,
+        BlockDriverCompletionFunc *cb, void *opaque);
     void (*bdrv_aio_cancel)(BlockDriverAIOCB *acb);
     int aiocb_size;
 
diff --git a/qemu/posix-aio-compat.c b/qemu/posix-aio-compat.c
index 394e807..6a718c0 100644
--- a/qemu/posix-aio-compat.c
+++ b/qemu/posix-aio-compat.c
@@ -15,6 +15,7 @@
 #include <unistd.h>
 #include <errno.h>
 #include <sys/time.h>
+#include <stdlib.h>
 #include "osdep.h"
 
 #include "posix-aio-compat.h"
@@ -27,6 +28,10 @@ static int cur_threads = 0;
 static int idle_threads = 0;
 static TAILQ_HEAD(, qemu_paiocb) request_list;
 
+#define QEMU_AIO_READ         0x0001
+#define QEMU_AIO_WRITE        0x0002
+#define QEMU_AIO_FLUSH        0x0008
+
 static void *aio_thread(void *unused)
 {
     sigset_t set;
@@ -67,16 +72,25 @@ static void *aio_thread(void *unused)
         while (offset < aiocb->aio_nbytes) {
             ssize_t len;
 
-            if (aiocb->is_write)
+            switch (aiocb->aio_type) {
+            case QEMU_AIO_FLUSH:
+                len = fdatasync(aiocb->aio_fildes);
+                break;
+            case QEMU_AIO_WRITE:
                 len = pwrite(aiocb->aio_fildes,
                              (const char *)aiocb->aio_buf + offset,
                              aiocb->aio_nbytes - offset,
                              aiocb->aio_offset + offset);
-            else
+                break;
+            case QEMU_AIO_READ:
                 len = pread(aiocb->aio_fildes,
                             (char *)aiocb->aio_buf + offset,
                             aiocb->aio_nbytes - offset,
                             aiocb->aio_offset + offset);
+                break;
+            default:
+                abort();
+            }
 
             if (len == -1 && errno == EINTR)
                 continue;
@@ -129,9 +143,9 @@ int qemu_paio_init(struct qemu_paioinit *aioinit)
     return 0;
 }
 
-static int qemu_paio_submit(struct qemu_paiocb *aiocb, int is_write)
+static int qemu_paio_submit(struct qemu_paiocb *aiocb, int aio_type)
 {
-    aiocb->is_write = is_write;
+    aiocb->aio_type = aio_type;
     aiocb->ret = -EINPROGRESS;
     aiocb->active = 0;
     pthread_mutex_lock(&lock);
@@ -146,12 +160,17 @@ static int qemu_paio_submit(struct qemu_paiocb *aiocb, int is_write)
 
 int qemu_paio_read(struct qemu_paiocb *aiocb)
 {
-    return qemu_paio_submit(aiocb, 0);
+    return qemu_paio_submit(aiocb, QEMU_AIO_READ);
 }
 
 int qemu_paio_write(struct qemu_paiocb *aiocb)
 {
-    return qemu_paio_submit(aiocb, 1);
+    return qemu_paio_submit(aiocb, QEMU_AIO_WRITE);
+}
+
+int qemu_paio_flush(struct qemu_paiocb *aiocb)
+{
+    return qemu_paio_submit(aiocb, QEMU_AIO_FLUSH);
 }
 
 ssize_t qemu_paio_return(struct qemu_paiocb *aiocb)
diff --git a/qemu/posix-aio-compat.h b/qemu/posix-aio-compat.h
index 5dddd71..56acaa0 100644
--- a/qemu/posix-aio-compat.h
+++ b/qemu/posix-aio-compat.h
@@ -34,7 +34,7 @@ struct qemu_paiocb
 
     /* private */
     TAILQ_ENTRY(qemu_paiocb) node;
-    int is_write;
+    int aio_type;
     ssize_t ret;
     int active;
 };
@@ -49,6 +49,7 @@ struct qemu_paioinit
 int qemu_paio_init(struct qemu_paioinit *aioinit);
 int qemu_paio_read(struct qemu_paiocb *aiocb);
 int qemu_paio_write(struct qemu_paiocb *aiocb);
+int qemu_paio_flush(struct qemu_paiocb *aiocb);
 int qemu_paio_error(struct qemu_paiocb *aiocb);
 ssize_t qemu_paio_return(struct qemu_paiocb *aiocb);
 int qemu_paio_cancel(int fd, struct qemu_paiocb *aiocb);
-- 
1.6.3.rc4.29.g8146