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 <[EMAIL PROTECTED]> 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) ------------------------------------------------------------------------- This SF.net email is sponsored by the 2008 JavaOne(SM) Conference Don't miss this year's exciting event. There's still time to save $100. Use priority code J8TL2D2. http://ad.doubleclick.net/clk;198757673;13503038;p?http://java.sun.com/javaone _______________________________________________ kvm-devel mailing list kvm-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/kvm-devel