All of lore.kernel.org
 help / color / mirror / Atom feed
From: Laurent Vivier <Laurent.Vivier@bull.net>
Cc: qemu-devel@nongnu.org
Subject: [Qemu-devel] [PATCH 2/5] Move AIO
Date: Wed, 23 Jan 2008 17:12:54 +0100	[thread overview]
Message-ID: <120110477478@bull.net> (raw)
In-Reply-To: <1201104773738@bull.net>


This patche moves raw AIO part from block-raw-posix.c to qemu-aio-raw.c to
be able to use raw AIO from other files.

Laurent
---
 Makefile          |    2 
 Makefile.target   |    2 
 block-raw-posix.c |  205 ++-------------------------------------------
 qemu-aio-posix.c  |  241 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 qemu-aio-posix.h  |   39 ++++++++
 5 files changed, 293 insertions(+), 196 deletions(-)

Index: qemu/Makefile.target
===================================================================
--- qemu.orig/Makefile.target	2008-01-23 09:18:17.000000000 +0100
+++ qemu/Makefile.target	2008-01-23 09:19:30.000000000 +0100
@@ -398,7 +398,7 @@ VL_OBJS=vl.o osdep.o monitor.o pci.o loa
 ifdef CONFIG_WIN32
 VL_OBJS+=block-raw-win32.o
 else
-VL_OBJS+=block-raw-posix.o
+VL_OBJS+=block-raw-posix.o qemu-aio-posix.o
 endif
 
 ifdef CONFIG_ALSA
Index: qemu/block-raw-posix.c
===================================================================
--- qemu.orig/block-raw-posix.c	2008-01-23 09:19:16.000000000 +0100
+++ qemu/block-raw-posix.c	2008-01-23 09:19:30.000000000 +0100
@@ -28,7 +28,7 @@
 #endif
 #include "block_int.h"
 #include <assert.h>
-#include <aio.h>
+#include "qemu-aio-posix.h"
 
 #ifdef CONFIG_COCOA
 #include <paths.h>
@@ -75,7 +75,7 @@
 #define FD_OPEN_TIMEOUT 1000
 
 typedef struct BDRVRawState {
-    int fd;
+    int fd;	/* must be the first field for qemu-aio-posix.c */
     int type;
     unsigned int lseek_err_cnt;
 #if defined(__linux__)
@@ -233,180 +233,18 @@ label__raw_write__success:
 /***********************************************************/
 /* Unix AIO using POSIX AIO */
 
-typedef struct RawAIOCB {
-    BlockDriverAIOCB common;
-    struct aiocb aiocb;
-    struct RawAIOCB *next;
-} RawAIOCB;
-
-static int aio_sig_num = SIGUSR2;
-static RawAIOCB *first_aio; /* AIO issued */
-static int aio_initialized = 0;
-
-static void aio_signal_handler(int signum)
-{
-#ifndef QEMU_IMG
-    CPUState *env = cpu_single_env;
-    if (env) {
-        /* stop the currently executing cpu because a timer occured */
-        cpu_interrupt(env, CPU_INTERRUPT_EXIT);
-#ifdef USE_KQEMU
-        if (env->kqemu_enabled) {
-            kqemu_cpu_interrupt(env);
-        }
-#endif
-    }
-#endif
-}
-
-void qemu_aio_init(void)
-{
-    struct sigaction act;
-
-    aio_initialized = 1;
-
-    sigfillset(&act.sa_mask);
-    act.sa_flags = 0; /* do not restart syscalls to interrupt select() */
-    act.sa_handler = aio_signal_handler;
-    sigaction(aio_sig_num, &act, NULL);
-
-#if defined(__GLIBC__) && defined(__linux__)
-    {
-        /* XXX: aio thread exit seems to hang on RedHat 9 and this init
-           seems to fix the problem. */
-        struct aioinit ai;
-        memset(&ai, 0, sizeof(ai));
-        ai.aio_threads = 1;
-        ai.aio_num = 1;
-        ai.aio_idle_time = 365 * 100000;
-        aio_init(&ai);
-    }
-#endif
-}
-
-void qemu_aio_poll(void)
-{
-    RawAIOCB *acb, **pacb;
-    int ret;
-
-    for(;;) {
-        pacb = &first_aio;
-        for(;;) {
-            acb = *pacb;
-            if (!acb)
-                goto the_end;
-            ret = aio_error(&acb->aiocb);
-            if (ret == ECANCELED) {
-                /* remove the request */
-                *pacb = acb->next;
-                qemu_aio_release(acb);
-            } else if (ret != EINPROGRESS) {
-                /* end of aio */
-                if (ret == 0) {
-                    ret = aio_return(&acb->aiocb);
-                    if (ret == acb->aiocb.aio_nbytes)
-                        ret = 0;
-                    else
-                        ret = -EINVAL;
-                } else {
-                    ret = -ret;
-                }
-                /* remove the request */
-                *pacb = acb->next;
-                /* call the callback */
-                acb->common.cb(acb->common.opaque, ret);
-                qemu_aio_release(acb);
-                break;
-            } else {
-                pacb = &acb->next;
-            }
-        }
-    }
- the_end: ;
-}
-
-/* Wait for all IO requests to complete.  */
-void qemu_aio_flush(void)
-{
-    qemu_aio_wait_start();
-    qemu_aio_poll();
-    while (first_aio) {
-        qemu_aio_wait();
-    }
-    qemu_aio_wait_end();
-}
-
-/* wait until at least one AIO was handled */
-static sigset_t wait_oset;
-
-void qemu_aio_wait_start(void)
-{
-    sigset_t set;
-
-    if (!aio_initialized)
-        qemu_aio_init();
-    sigemptyset(&set);
-    sigaddset(&set, aio_sig_num);
-    sigprocmask(SIG_BLOCK, &set, &wait_oset);
-}
-
-void qemu_aio_wait(void)
-{
-    sigset_t set;
-    int nb_sigs;
-
-#ifndef QEMU_IMG
-    if (qemu_bh_poll())
-        return;
-#endif
-    sigemptyset(&set);
-    sigaddset(&set, aio_sig_num);
-    sigwait(&set, &nb_sigs);
-    qemu_aio_poll();
-}
-
-void qemu_aio_wait_end(void)
-{
-    sigprocmask(SIG_SETMASK, &wait_oset, NULL);
-}
-
-static RawAIOCB *raw_aio_setup(BlockDriverState *bs,
+static BlockDriverAIOCB *raw_aio_read(BlockDriverState *bs,
         int64_t sector_num, uint8_t *buf, int nb_sectors,
         BlockDriverCompletionFunc *cb, void *opaque)
 {
-    BDRVRawState *s = bs->opaque;
     RawAIOCB *acb;
 
     if (fd_open(bs) < 0)
         return NULL;
 
-    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;
-}
+    acb = qemu_aio_read(bs, sector_num * 512, buf, nb_sectors * 512,
+                        cb, opaque);
 
-static BlockDriverAIOCB *raw_aio_read(BlockDriverState *bs,
-        int64_t sector_num, uint8_t *buf, int nb_sectors,
-        BlockDriverCompletionFunc *cb, void *opaque)
-{
-    RawAIOCB *acb;
-
-    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 &acb->common;
 }
 
@@ -416,41 +254,20 @@ static BlockDriverAIOCB *raw_aio_write(B
 {
     RawAIOCB *acb;
 
-    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);
+    if (fd_open(bs) < 0)
         return NULL;
-    }
+
+    acb = qemu_aio_write(bs, sector_num * 512, buf, nb_sectors * 512,
+                         cb, opaque);
+
     return &acb->common;
 }
 
 static void raw_aio_cancel(BlockDriverAIOCB *blockacb)
 {
-    int ret;
     RawAIOCB *acb = (RawAIOCB *)blockacb;
-    RawAIOCB **pacb;
 
-    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(&acb->aiocb) == EINPROGRESS);
-    }
-
-    /* remove the callback from the queue */
-    pacb = &first_aio;
-    for(;;) {
-        if (*pacb == NULL) {
-            break;
-        } else if (*pacb == acb) {
-            *pacb = acb->next;
-            qemu_aio_release(acb);
-            break;
-        }
-        pacb = &acb->next;
-    }
+    qemu_aio_cancel(acb);
 }
 
 static void raw_close(BlockDriverState *bs)
Index: qemu/Makefile
===================================================================
--- qemu.orig/Makefile	2008-01-23 09:18:17.000000000 +0100
+++ qemu/Makefile	2008-01-23 09:19:30.000000000 +0100
@@ -136,7 +136,7 @@ QEMU_IMG_BLOCK_OBJS = $(BLOCK_OBJS)
 ifdef CONFIG_WIN32
 QEMU_IMG_BLOCK_OBJS += qemu-img-block-raw-win32.o
 else
-QEMU_IMG_BLOCK_OBJS += qemu-img-block-raw-posix.o
+QEMU_IMG_BLOCK_OBJS += qemu-img-block-raw-posix.o qemu-img-qemu-aio-posix.o
 endif
 
 ######################################################################
Index: qemu/qemu-aio-posix.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ qemu/qemu-aio-posix.c	2008-01-23 09:19:30.000000000 +0100
@@ -0,0 +1,241 @@
+/*
+ * QEMU Asynchronous I/O
+ *
+ * Copyright (c) 2006 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "qemu-common.h"
+#include <aio.h>
+#ifndef QEMU_IMG
+#include "qemu-timer.h"
+#include "exec-all.h"
+#endif
+#include "block_int.h"
+#include "qemu-aio-posix.h"
+
+static void aio_signal_handler(int signum)
+{
+#ifndef QEMU_IMG
+    CPUState *env = cpu_single_env;
+    if (env) {
+        /* stop the currently executing cpu because a timer occured */
+        cpu_interrupt(env, CPU_INTERRUPT_EXIT);
+#ifdef USE_KQEMU
+        if (env->kqemu_enabled) {
+            kqemu_cpu_interrupt(env);
+        }
+#endif
+    }
+#endif
+}
+
+static int aio_initialized = 0;
+static int aio_sig_num = SIGUSR2;
+static RawAIOCB *first_aio; /* AIO issued */
+
+void qemu_aio_init(void)
+{
+    struct sigaction act;
+
+    aio_initialized = 1;
+
+    sigfillset(&act.sa_mask);
+    act.sa_flags = 0; /* do not restart syscalls to interrupt select() */
+    act.sa_handler = aio_signal_handler;
+    sigaction(aio_sig_num, &act, NULL);
+
+#if defined(__GLIBC__) && defined(__linux__)
+    {
+        /* XXX: aio thread exit seems to hang on RedHat 9 and this init
+           seems to fix the problem. */
+        struct aioinit ai;
+        memset(&ai, 0, sizeof(ai));
+        ai.aio_threads = 1;
+        ai.aio_num = 1;
+        ai.aio_idle_time = 365 * 100000;
+        aio_init(&ai);
+    }
+#endif
+}
+
+void qemu_aio_poll(void)
+{
+    RawAIOCB *acb, **pacb;
+    int ret;
+
+    for(;;) {
+        pacb = &first_aio;
+        for(;;) {
+            acb = *pacb;
+            if (!acb)
+                goto the_end;
+            ret = aio_error(&acb->aiocb);
+            if (ret == ECANCELED) {
+                /* remove the request */
+                *pacb = acb->next;
+                qemu_aio_release(acb);
+            } else if (ret != EINPROGRESS) {
+                /* end of aio */
+                if (ret == 0) {
+                    ret = aio_return(&acb->aiocb);
+                    if (ret == acb->aiocb.aio_nbytes)
+                        ret = 0;
+                    else
+                        ret = -EINVAL;
+                } else {
+                    ret = -ret;
+                }
+                /* remove the request */
+                *pacb = acb->next;
+                /* call the callback */
+                acb->common.cb(acb->common.opaque, ret);
+                qemu_aio_release(acb);
+                break;
+            } else {
+                pacb = &acb->next;
+            }
+        }
+    }
+ the_end: ;
+}
+
+/* Wait for all IO requests to complete.  */
+void qemu_aio_flush(void)
+{
+    qemu_aio_wait_start();
+    qemu_aio_poll();
+    while (first_aio) {
+        qemu_aio_wait();
+    }
+    qemu_aio_wait_end();
+}
+
+/* wait until at least one AIO was handled */
+static sigset_t wait_oset;
+
+void qemu_aio_wait_start(void)
+{
+    sigset_t set;
+
+    if (!aio_initialized)
+        qemu_aio_init();
+    sigemptyset(&set);
+    sigaddset(&set, aio_sig_num);
+    sigprocmask(SIG_BLOCK, &set, &wait_oset);
+}
+
+void qemu_aio_wait(void)
+{
+    sigset_t set;
+    int nb_sigs;
+
+#ifndef QEMU_IMG
+    if (qemu_bh_poll())
+        return;
+#endif
+    sigemptyset(&set);
+    sigaddset(&set, aio_sig_num);
+    sigwait(&set, &nb_sigs);
+    qemu_aio_poll();
+}
+
+void qemu_aio_wait_end(void)
+{
+    sigprocmask(SIG_SETMASK, &wait_oset, NULL);
+}
+
+static RawAIOCB *qemu_aio_setup(BlockDriverState *bs,
+        int64_t offset, uint8_t *buf, int nb_bytes,
+        BlockDriverCompletionFunc *cb, void *opaque)
+{
+    int fd = *(int*)bs->opaque;
+    RawAIOCB *acb;
+
+    acb = qemu_aio_get(bs, cb, opaque);
+    if (!acb)
+        return NULL;
+    acb->aiocb.aio_fildes = 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_bytes;
+    acb->aiocb.aio_offset = offset;
+    acb->next = first_aio;
+    first_aio = acb;
+    return acb;
+}
+
+RawAIOCB *qemu_aio_read(BlockDriverState *bs,
+        int64_t offset, uint8_t *buf, int nb_bytes,
+        BlockDriverCompletionFunc *cb, void *opaque)
+{
+    RawAIOCB *acb;
+
+    acb = qemu_aio_setup(bs, offset, buf, nb_bytes, cb, opaque);
+    if (!acb)
+        return NULL;
+    if (aio_read(&acb->aiocb) < 0) {
+        qemu_aio_release(acb);
+        return NULL;
+    }
+    return acb;
+}
+
+RawAIOCB *qemu_aio_write(BlockDriverState *bs,
+        int64_t offset, const uint8_t *buf, int nb_bytes,
+        BlockDriverCompletionFunc *cb, void *opaque)
+{
+    RawAIOCB *acb;
+
+    acb = qemu_aio_setup(bs, offset, (uint8_t*)buf, nb_bytes, cb, opaque);
+    if (!acb)
+        return NULL;
+    if (aio_write(&acb->aiocb) < 0) {
+        qemu_aio_release(acb);
+        return NULL;
+    }
+    return acb;
+}
+
+void qemu_aio_cancel(RawAIOCB *acb)
+{
+    int ret;
+    RawAIOCB **pacb;
+
+    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(&acb->aiocb) == EINPROGRESS);
+    }
+
+    /* remove the callback from the queue */
+    pacb = &first_aio;
+    for(;;) {
+        if (*pacb == NULL) {
+            break;
+        } else if (*pacb == acb) {
+            *pacb = acb->next;
+            qemu_aio_release(acb);
+            break;
+        }
+        pacb = &acb->next;
+    }
+}
Index: qemu/qemu-aio-posix.h
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ qemu/qemu-aio-posix.h	2008-01-23 09:19:30.000000000 +0100
@@ -0,0 +1,39 @@
+/*
+ * QEMU Asynchronous I/O
+ *
+ * Copyright (c) 2006 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <aio.h>
+
+typedef struct RawAIOCB {
+    BlockDriverAIOCB common;
+    struct aiocb aiocb;
+    struct RawAIOCB *next;
+} RawAIOCB;
+
+RawAIOCB *qemu_aio_read(BlockDriverState *bs,
+        int64_t offset, uint8_t *buf, int nb_bytes,
+        BlockDriverCompletionFunc *cb, void *opaque);
+RawAIOCB *qemu_aio_write(BlockDriverState *bs,
+        int64_t offset, const uint8_t *buf, int nb_bytes,
+        BlockDriverCompletionFunc *cb, void *opaque);
+void qemu_aio_cancel(RawAIOCB *acb);

  reply	other threads:[~2008-01-23 16:10 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-01-23 16:12 [Qemu-devel] [PATCH 0/5] SCSI passthrough cleanup Laurent Vivier
2008-01-23 16:12 ` [Qemu-devel] [PATCH 1/5] reverse scsi-generic Laurent Vivier
2008-01-23 16:12   ` Laurent Vivier [this message]
2008-01-23 16:12     ` [Qemu-devel] [PATCH 3/5] Add block SG interface Laurent Vivier
2008-01-23 16:12       ` [Qemu-devel] [PATCH 4/5] DVD movie support Laurent Vivier
2008-01-23 16:12         ` [Qemu-devel] [PATCH 5/5] SCSI device DMA split Laurent Vivier
2008-01-23 20:52 ` [Qemu-devel] [PATCH 0/5] SCSI passthrough cleanup Fabrice Bellard
2008-01-24  8:17   ` Laurent Vivier

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=120110477478@bull.net \
    --to=laurent.vivier@bull.net \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.