From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1JHiBB-0005A2-3P for qemu-devel@nongnu.org; Wed, 23 Jan 2008 11:10:21 -0500 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1JHiB4-00052w-Ld for qemu-devel@nongnu.org; Wed, 23 Jan 2008 11:10:18 -0500 Received: from [199.232.76.173] (helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1JHiB4-00052W-Dh for qemu-devel@nongnu.org; Wed, 23 Jan 2008 11:10:14 -0500 Received: from ecfrec.frec.bull.fr ([129.183.4.8]) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1JHiB3-0005Y1-IE for qemu-devel@nongnu.org; Wed, 23 Jan 2008 11:10:14 -0500 Received: from localhost (localhost [127.0.0.1]) by ecfrec.frec.bull.fr (Postfix) with ESMTP id C945B19D9B1 for ; Wed, 23 Jan 2008 17:09:48 +0100 (CET) Received: from ecfrec.frec.bull.fr ([127.0.0.1]) by localhost (ecfrec.frec.bull.fr [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 12862-05 for ; Wed, 23 Jan 2008 17:09:44 +0100 (CET) Received: from ecn002.frec.bull.fr (ecn002.frec.bull.fr [129.183.4.6]) by ecfrec.frec.bull.fr (Postfix) with ESMTP id 3C4C619D92B for ; Wed, 23 Jan 2008 17:09:23 +0100 (CET) In-Reply-To: <1201104773738@bull.net> Date: Wed, 23 Jan 2008 17:12:54 +0100 Message-Id: <120110477478@bull.net> Mime-Version: 1.0 From: Laurent Vivier Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="iso-8859-1" Subject: [Qemu-devel] [PATCH 2/5] Move AIO Reply-To: Laurent Vivier , qemu-devel@nongnu.org List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: qemu-devel@nongnu.org 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=20 Makefile.target | 2=20 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 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- 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=3Dvl.o osdep.o monitor.o pci.o loa ifdef CONFIG_WIN32 VL_OBJS+=3Dblock-raw-win32.o else -VL_OBJS+=3Dblock-raw-posix.o +VL_OBJS+=3Dblock-raw-posix.o qemu-aio-posix.o endif =20 ifdef CONFIG_ALSA Index: qemu/block-raw-posix.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- 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 -#include +#include "qemu-aio-posix.h" =20 #ifdef CONFIG_COCOA #include @@ -75,7 +75,7 @@ #define FD_OPEN_TIMEOUT 1000 =20 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 */ =20 -typedef struct RawAIOCB { - BlockDriverAIOCB common; - struct aiocb aiocb; - struct RawAIOCB *next; -} RawAIOCB; - -static int aio_sig_num =3D SIGUSR2; -static RawAIOCB *first_aio; /* AIO issued */ -static int aio_initialized =3D 0; - -static void aio_signal_handler(int signum) -{ -#ifndef QEMU_IMG - CPUState *env =3D 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 =3D 1; - - sigfillset(&act.sa_mask); - act.sa_flags =3D 0; /* do not restart syscalls to interrupt select() */ - act.sa_handler =3D 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 =3D 1; - ai.aio_num =3D 1; - ai.aio_idle_time =3D 365 * 100000; - aio_init(&ai); - } -#endif -} - -void qemu_aio_poll(void) -{ - RawAIOCB *acb, **pacb; - int ret; - - for(;;) { - pacb =3D &first_aio; - for(;;) { - acb =3D *pacb; - if (!acb) - goto the_end; - ret =3D aio_error(&acb->aiocb); - if (ret =3D=3D ECANCELED) { - /* remove the request */ - *pacb =3D acb->next; - qemu_aio_release(acb); - } else if (ret !=3D EINPROGRESS) { - /* end of aio */ - if (ret =3D=3D 0) { - ret =3D aio_return(&acb->aiocb); - if (ret =3D=3D acb->aiocb.aio_nbytes) - ret =3D 0; - else - ret =3D -EINVAL; - } else { - ret =3D -ret; - } - /* remove the request */ - *pacb =3D acb->next; - /* call the callback */ - acb->common.cb(acb->common.opaque, ret); - qemu_aio_release(acb); - break; - } else { - pacb =3D &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 =3D bs->opaque; RawAIOCB *acb; =20 if (fd_open(bs) < 0) return NULL; =20 - acb =3D qemu_aio_get(bs, cb, opaque); - if (!acb) - return NULL; - acb->aiocb.aio_fildes =3D s->fd; - acb->aiocb.aio_sigevent.sigev_signo =3D aio_sig_num; - acb->aiocb.aio_sigevent.sigev_notify =3D SIGEV_SIGNAL; - acb->aiocb.aio_buf =3D buf; - acb->aiocb.aio_nbytes =3D nb_sectors * 512; - acb->aiocb.aio_offset =3D sector_num * 512; - acb->next =3D first_aio; - first_aio =3D acb; - return acb; -} + acb =3D qemu_aio_read(bs, sector_num * 512, buf, nb_sectors * 512, + cb, opaque); =20 -static BlockDriverAIOCB *raw_aio_read(BlockDriverState *bs, - int64_t sector_num, uint8_t *buf, int nb_sectors, - BlockDriverCompletionFunc *cb, void *opaque) -{ - RawAIOCB *acb; - - acb =3D 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; } =20 @@ -416,41 +254,20 @@ static BlockDriverAIOCB *raw_aio_write(B { RawAIOCB *acb; =20 - acb =3D raw_aio_setup(bs, sector_num, (uint8_t*)buf, nb_sectors, cb, o= paque); - if (!acb) - return NULL; - if (aio_write(&acb->aiocb) < 0) { - qemu_aio_release(acb); + if (fd_open(bs) < 0) return NULL; - } + + acb =3D qemu_aio_write(bs, sector_num * 512, buf, nb_sectors * 512, + cb, opaque); + return &acb->common; } =20 static void raw_aio_cancel(BlockDriverAIOCB *blockacb) { - int ret; RawAIOCB *acb =3D (RawAIOCB *)blockacb; - RawAIOCB **pacb; =20 - ret =3D aio_cancel(acb->aiocb.aio_fildes, &acb->aiocb); - if (ret =3D=3D AIO_NOTCANCELED) { - /* fail safe: if the aio could not be canceled, we wait for - it */ - while (aio_error(&acb->aiocb) =3D=3D EINPROGRESS); - } - - /* remove the callback from the queue */ - pacb =3D &first_aio; - for(;;) { - if (*pacb =3D=3D NULL) { - break; - } else if (*pacb =3D=3D acb) { - *pacb =3D acb->next; - qemu_aio_release(acb); - break; - } - pacb =3D &acb->next; - } + qemu_aio_cancel(acb); } =20 static void raw_close(BlockDriverState *bs) Index: qemu/Makefile =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- 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 =3D $(BLOCK_OBJS) ifdef CONFIG_WIN32 QEMU_IMG_BLOCK_OBJS +=3D qemu-img-block-raw-win32.o else -QEMU_IMG_BLOCK_OBJS +=3D qemu-img-block-raw-posix.o +QEMU_IMG_BLOCK_OBJS +=3D qemu-img-block-raw-posix.o qemu-img-qemu-aio-posi= x.o endif =20 ###################################################################### Index: qemu/qemu-aio-posix.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- /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"), t= o deal + * in the Software without restriction, including without limitation the r= ights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or se= ll + * 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 OT= HER + * 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 +#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 =3D 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 =3D 0; +static int aio_sig_num =3D SIGUSR2; +static RawAIOCB *first_aio; /* AIO issued */ + +void qemu_aio_init(void) +{ + struct sigaction act; + + aio_initialized =3D 1; + + sigfillset(&act.sa_mask); + act.sa_flags =3D 0; /* do not restart syscalls to interrupt select() */ + act.sa_handler =3D 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 =3D 1; + ai.aio_num =3D 1; + ai.aio_idle_time =3D 365 * 100000; + aio_init(&ai); + } +#endif +} + +void qemu_aio_poll(void) +{ + RawAIOCB *acb, **pacb; + int ret; + + for(;;) { + pacb =3D &first_aio; + for(;;) { + acb =3D *pacb; + if (!acb) + goto the_end; + ret =3D aio_error(&acb->aiocb); + if (ret =3D=3D ECANCELED) { + /* remove the request */ + *pacb =3D acb->next; + qemu_aio_release(acb); + } else if (ret !=3D EINPROGRESS) { + /* end of aio */ + if (ret =3D=3D 0) { + ret =3D aio_return(&acb->aiocb); + if (ret =3D=3D acb->aiocb.aio_nbytes) + ret =3D 0; + else + ret =3D -EINVAL; + } else { + ret =3D -ret; + } + /* remove the request */ + *pacb =3D acb->next; + /* call the callback */ + acb->common.cb(acb->common.opaque, ret); + qemu_aio_release(acb); + break; + } else { + pacb =3D &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 =3D *(int*)bs->opaque; + RawAIOCB *acb; + + acb =3D qemu_aio_get(bs, cb, opaque); + if (!acb) + return NULL; + acb->aiocb.aio_fildes =3D fd; + acb->aiocb.aio_sigevent.sigev_signo =3D aio_sig_num; + acb->aiocb.aio_sigevent.sigev_notify =3D SIGEV_SIGNAL; + acb->aiocb.aio_buf =3D buf; + acb->aiocb.aio_nbytes =3D nb_bytes; + acb->aiocb.aio_offset =3D offset; + acb->next =3D first_aio; + first_aio =3D 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 =3D 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 =3D 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 =3D aio_cancel(acb->aiocb.aio_fildes, &acb->aiocb); + if (ret =3D=3D AIO_NOTCANCELED) { + /* fail safe: if the aio could not be canceled, we wait for + it */ + while (aio_error(&acb->aiocb) =3D=3D EINPROGRESS); + } + + /* remove the callback from the queue */ + pacb =3D &first_aio; + for(;;) { + if (*pacb =3D=3D NULL) { + break; + } else if (*pacb =3D=3D acb) { + *pacb =3D acb->next; + qemu_aio_release(acb); + break; + } + pacb =3D &acb->next; + } +} Index: qemu/qemu-aio-posix.h =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- /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"), t= o deal + * in the Software without restriction, including without limitation the r= ights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or se= ll + * 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 OT= HER + * 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 + +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);