* Zhi Yong Wu <wuzhy@xxxxxxxxxxxxxxxxxx> [2011-08-01 01:30]: > +static AIOPool block_queue_pool = { > + .aiocb_size = sizeof(struct BlockDriverAIOCB), > + .cancel = qemu_block_queue_cancel, > +}; > + > +static void qemu_block_queue_callback(void *opaque, int ret) > +{ > + BlockDriverAIOCB *acb = opaque; > + > + qemu_aio_release(acb); > +} > + So, here we really want to invoke the original commands callback, and then free the request here (via qemu_aio_release()). see below. > +BlockDriverAIOCB *qemu_block_queue_enqueue(BlockQueue *queue, > + BlockDriverState *bs, > + BlockRequestHandler *handler, > + int64_t sector_num, > + QEMUIOVector *qiov, > + int nb_sectors, > + BlockDriverCompletionFunc *cb, > + void *opaque) > +{ > + BlockIORequest *request; > + BlockDriverAIOCB *acb; > + > + request = qemu_malloc(sizeof(BlockIORequest)); > + request->bs = bs; > + request->handler = handler; > + request->sector_num = sector_num; > + request->qiov = qiov; > + request->nb_sectors = nb_sectors; > + request->cb = cb; > + request->opaque = opaque; > + > + QTAILQ_INSERT_TAIL(&queue->requests, request, entry); > + > + acb = qemu_aio_get(&block_queue_pool, bs, > + qemu_block_queue_callback, opaque); > + request->acb = acb; > + > + return acb; > +} > + > +int qemu_block_queue_handler(BlockIORequest *request) > +{ > + int ret; > + BlockDriverAIOCB *res; > + > + /* indicate this req is from block queue */ > + request->bs->req_from_queue = true; > + > + res = request->handler(request->bs, request->sector_num, > + request->qiov, request->nb_sectors, > + request->cb, request->opaque); > + > + if (request->acb) { > + qemu_block_queue_callback(request->acb, 0); > + } > + > + ret = (res == NULL) ? 0 : 1; > + > + return ret; > +} You don't want to malloc the BlockIORequest directly in _enqueue(), rather you want to allocate that from your AIOPool via qemu_aio_get(). As it is now, we're allocating two BlockIORequests (malloc and then a aio_get()). You'll need a BlockDriverAIOCB in the BlockIORequest structure. Then in your queue_handler, instead of passing the original read or write callback (request->cb), you want to hook the block_queue callback (qemu_block_queue_callback()), in that callback you can then invoke the request callback and then release the request. The request should be, only one malloc (via the pool which will re-use the memory instead of incuring a malloc on every request), and then you release the memory back to the pool once your request is complete, which you'll know after wiring up the block_queue callback to the completion of the request's handler. And then since we don't double allocate, you won't need to do the qemu_free(request) in block.c in block_timer... -- Ryan Harper Software Engineer; Linux Technology Center IBM Corp., Austin, Tx ryanh@xxxxxxxxxx -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html