/**QEMUaioimplementation**CopyrightIBM,Corp.2008**Authors:*AnthonyLiguori<aliguori@us.ibm.com>**ThisworkislicensedunderthetermsoftheGNUGPL,version2.See*theCOPYINGfileinthetop-leveldirectory.**/#include"qemu-common.h"#include"block.h"#include"sys-queue.h"#include"qemu_socket.h"typedefstructAioHandlerAioHandler;/* The list of registered AIO handlers */staticLIST_HEAD(,AioHandler)aio_handlers;/*Thisisasimplelockusedtoprotecttheaio_handlerslist.Specifically,*it'susedtoensurethatnocallbacksareremovedwhilewe'rewalkingand*dispatchingcallbacks.*/staticintwalking_handlers;structAioHandler{intfd;IOHandler*io_read;IOHandler*io_write;AioFlushHandler*io_flush;intdeleted;void*opaque;LIST_ENTRY(AioHandler)node;};staticAioHandler*find_aio_handler(intfd){AioHandler*node;LIST_FOREACH(node,&aio_handlers,node){if(node->fd==fd)
}returnNULL;}intqemu_aio_set_fd_handler(intfd,IOHandler*io_read,IOHandler*io_write,AioFlushHandler*io_flush,void*opaque){AioHandler*node;node=find_aio_handler(fd);/* Are we deleting the fd handler? */if(!io_read&&!io_write){if(node){/* If the lock is held, just mark the node as deleted */if(walking_handlers)node->deleted=1;else{/*Otherwise,deleteitforreal.Wecan'tjustmarkitas*deletedbecausedeletednodesareonlycleanedupafter*releasingthewalking_handlerslock.*/LIST_REMOVE(node,node);qemu_free(node);}}}else{if(node==NULL){/* Alloc and insert if it's not already there */node=qemu_mallocz(sizeof(AioHandler));node->fd=fd;LIST_INSERT_HEAD(&aio_handlers,node,node);}/* Update handler with latest information */node->io_read=io_read;node->io_write=io_write;node->io_flush=io_flush;node->opaque=opaque;}qemu_set_fd_handler2(fd,NULL,io_read,io_write,opaque);return0;}voidqemu_aio_flush(void){AioHandler*node;intret;do{ret=0;
/* fill fd sets */LIST_FOREACH(node,&aio_handlers,node){/*Iftherearen'tpendingAIOoperations,don'tinvokecallbacks.*Otherwise,iftherearenoAIOrequests,qemu_aio_wait()would*waitindefinitely.*/if(node->io_flush&&node->io_flush(node->opaque)==0)continue;if(!node->deleted&&node->io_read){FD_SET(node->fd,&rdfds);max_fd=MAX(max_fd,node->fd+1);}if(!node->deleted&&node->io_write){FD_SET(node->fd,&wrfds);max_fd=MAX(max_fd,node->fd+1);}}walking_handlers=0;/* No AIO operations? Get us out of here */if(max_fd==-1)break;/* wait until next event */ret=select(max_fd,&rdfds,&wrfds,NULL,NULL);if(ret==-1&&errno==EINTR)continue;/* if we have any readable fds, dispatch event */if(ret>0){walking_handlers=1;/*wehavetowalkverycarefullyincase*qemu_aio_set_fd_handleriscalledwhilewe'rewalking*/node=LIST_FIRST(&aio_handlers);while(node){AioHandler*tmp;if(!node->deleted&&FD_ISSET(node->fd,&rdfds)&&node->io_read){node->io_read(node->opaque);}if(!node->deleted&&FD_ISSET(node->fd,&wrfds)&&node->io_write){node->io_write(node->opaque);}tmp=node;node=LIST_NEXT(node,node);if(tmp->deleted){LIST_REMOVE(tmp,node);qemu_free(tmp);}}walking_handlers=0;}}while(ret==0);}