[PATCH 2/3] Split out posix-aio code

Anthony Liguori
2008-04-17T19:26:51Z

This patch moves the posix-aio code into a separate file. It's strictly code
motion, no new functionality is introduced.

Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>

diff --git a/Makefile b/Makefile
index a8df278..916f071 100644
--- a/Makefile
+++ b/Makefile
@@ -139,7 +139,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-aio-posix.o
endif

######################################################################
diff --git a/Makefile.target b/Makefile.target
index 75de753..f635d68 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -485,7 +485,7 @@ OBJS=vl.o osdep.o monitor.o pci.o loader.o isa_mmio.o
ifdef CONFIG_WIN32
OBJS+=block-raw-win32.o
else
-OBJS+=block-raw-posix.o
+OBJS+=block-raw-posix.o aio-posix.o
endif

LIBS+=-lz
diff --git a/aio-posix.c b/aio-posix.c
new file mode 100644
index 0000000..b5fea7d
--- /dev/null
+++ b/aio-posix.c
@@ -0,0 +1,290 @@
+/*
+ * Block driver for RAW files (posix)
+ *
+ * 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"
+#ifndef QEMU_IMG
+#include "qemu-timer.h"
+#include "exec-all.h"
+#endif
+#include "sysemu.h"
+#include "block_int.h"
+#include "block-aio.h"
+#include <assert.h>
+#include <aio.h>
+
+#ifdef CONFIG_COCOA
+#include <paths.h>
+#include <sys/param.h>
+#include <IOKit/IOKitLib.h>
+#include <IOKit/IOBSD.h>
+#include <IOKit/storage/IOMediaBSDClient.h>
+#include <IOKit/storage/IOMedia.h>
+#include <IOKit/storage/IOCDMedia.h>
+//#include <IOKit/storage/IOCDTypes.h>
+#include <CoreFoundation/CoreFoundation.h>
+#endif
+
+#ifdef __sun__
+#define _POSIX_PTHREAD_SEMANTICS 1
+#include <signal.h>
+#include <sys/dkio.h>
+#endif
+#ifdef __linux__
+#include <sys/ioctl.h>
+#include <linux/cdrom.h>
+#include <linux/fd.h>
+#endif
+#ifdef __FreeBSD__
+#include <sys/disk.h>
+#endif
+
+/***********************************************************/
+/* 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 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 void pa_poll(void *opaque)
+{
+ 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: ;
+}
+
+static void pa_init(void)
+{
+ struct sigaction act;
+
+#ifndef QEMU_IMG
+ qemu_register_poll(pa_poll, NULL);
+#endif
+
+ 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
+}
+
+/* wait until at least one AIO was handled */
+static sigset_t wait_oset;
+
+static void pa_wait_start(void)
+{
+ sigset_t set;
+
+ sigemptyset(&set);
+ sigaddset(&set, aio_sig_num);
+ sigprocmask(SIG_BLOCK, &set, &wait_oset);
+}
+
+static void pa_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);
+ pa_poll(NULL);
+}
+
+static void pa_wait_end(void)
+{
+ sigprocmask(SIG_SETMASK, &wait_oset, NULL);
+}
+
+/* Wait for all IO requests to complete. */
+static void pa_flush(void)
+{
+ pa_wait_start();
+ pa_poll(NULL);
+ while (first_aio) {
+ pa_wait();
+ }
+ pa_wait_end();
+}
+
+static RawAIOCB *raw_aio_setup(BlockDriverState *bs, int fd,
+ int64_t sector_num, uint8_t *buf, int nb_sectors,
+ BlockDriverCompletionFunc *cb, void *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;
+ if (nb_sectors < 0)
+ acb->aiocb.aio_nbytes = -nb_sectors;
+ else
+ acb->aiocb.aio_nbytes = nb_sectors * 512;
+ acb->aiocb.aio_offset = sector_num * 512;
+ acb->next = first_aio;
+ first_aio = acb;
+ return acb;
+}
+
+static BlockDriverAIOCB *pa_submit(BlockDriverState *bs,
+ int fd, int64_t sector_num,
+ void *buf, int nb_sectors, int write,
+ BlockDriverCompletionFunc *cb,
+ void *opaque)
+{
+ RawAIOCB *acb;
+ int err;
+
+ acb = raw_aio_setup(bs, fd, sector_num, buf, nb_sectors, cb, opaque);
+ if (!acb)
+ return NULL;
+
+ if (write)
+ err = aio_write(&acb->aiocb);
+ else
+ err = aio_read(&acb->aiocb);
+
+ if (err < 0) {
+ qemu_aio_release(acb);
+ return NULL;
+ }
+ return &acb->common;
+}
+
+static void pa_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;
+ }
+}
+
+static AIODriver posix_aio_drv = {
+ .name = "posix",
+ .aiocb_size = sizeof(RawAIOCB),
+ .aio_init = pa_init,
+ .aio_wait_start = pa_wait_start,
+ .aio_wait = pa_wait,
+ .aio_wait_end = pa_wait_end,
+ .aio_flush = pa_flush,
+ .aio_submit = pa_submit,
+ .aio_cancel = pa_cancel,
+};
+
+int posix_aio_init(void)
+{
+ return qemu_register_aio(&posix_aio_drv);
+}
diff --git a/block-raw-posix.c b/block-raw-posix.c
index fee8422..f0a111a 100644
--- a/block-raw-posix.c
+++ b/block-raw-posix.c
@@ -29,7 +29,6 @@
#include "block_int.h"
#include "block-aio.h"
#include <assert.h>
-#include <aio.h>

#ifdef CONFIG_COCOA
#include <paths.h>
@@ -232,245 +231,10 @@ 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 */
+/* AIO Interface */
+
static int aio_initialized = 0;

-static void pa_poll(void *opaque);
-static void pa_wait_start(void);
-static void pa_wait(void);
-static void pa_wait_end(void);
-
-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 void pa_init(void)
-{
- struct sigaction act;
-
-#ifndef QEMU_IMG
- qemu_register_poll(pa_poll, NULL);
-#endif
-
- 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
-}
-
-static void pa_poll(void *opaque)
-{
- 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. */
-static void pa_flush(void)
-{
- pa_wait_start();
- pa_poll(NULL);
- while (first_aio) {
- pa_wait();
- }
- pa_wait_end();
-}
-
-/* wait until at least one AIO was handled */
-static sigset_t wait_oset;
-
-static void pa_wait_start(void)
-{
- sigset_t set;
-
- sigemptyset(&set);
- sigaddset(&set, aio_sig_num);
- sigprocmask(SIG_BLOCK, &set, &wait_oset);
-}
-
-static void pa_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);
- pa_poll(NULL);
-}
-
-static void pa_wait_end(void)
-{
- sigprocmask(SIG_SETMASK, &wait_oset, NULL);
-}
-
-static RawAIOCB *raw_aio_setup(BlockDriverState *bs, int fd,
- int64_t sector_num, uint8_t *buf, int nb_sectors,
- BlockDriverCompletionFunc *cb, void *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 = fd;
- acb->aiocb.aio_sigevent.sigev_signo = aio_sig_num;
- acb->aiocb.aio_sigevent.sigev_notify = SIGEV_SIGNAL;
- acb->aiocb.aio_buf = buf;
- if (nb_sectors < 0)
- acb->aiocb.aio_nbytes = -nb_sectors;
- else
- acb->aiocb.aio_nbytes = nb_sectors * 512;
- acb->aiocb.aio_offset = sector_num * 512;
- acb->next = first_aio;
- first_aio = acb;
- return acb;
-}
-
-static BlockDriverAIOCB *pa_submit(BlockDriverState *bs,
- int fd, int64_t sector_num,
- void *buf, int nb_sectors, int write,
- BlockDriverCompletionFunc *cb,
- void *opaque)
-{
- RawAIOCB *acb;
- int err;
-
- acb = raw_aio_setup(bs, fd, sector_num, buf, nb_sectors, cb, opaque);
- if (!acb)
- return NULL;
-
- if (write)
- err = aio_write(&acb->aiocb);
- else
- err = aio_read(&acb->aiocb);
-
- if (err < 0) {
- qemu_aio_release(acb);
- return NULL;
- }
- return &acb->common;
-}
-
-static void pa_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;
- }
-}
-
-static AIODriver posix_aio_drv = {
- .name = "posix",
- .aiocb_size = sizeof(RawAIOCB),
- .aio_init = pa_init,
- .aio_wait_start = pa_wait_start,
- .aio_wait = pa_wait,
- .aio_wait_end = pa_wait_end,
- .aio_flush = pa_flush,
- .aio_submit = pa_submit,
- .aio_cancel = pa_cancel,
-};
-
-int posix_aio_init(void)
-{
- return qemu_register_aio(&posix_aio_drv);
-}
-
void qemu_aio_init(void)
{
if (aio_initialized)