Il 21/08/2014 13:56, Fam Zheng ha scritto:
> + BlockDriverAIOCB *save = g_new(BlockDriverAIOCB, 1);
> + save->cb = acb->cb;
> + save->opaque = acb->opaque;
> + acb->cb = bdrv_aio_cancel_async_cb;
> + acb->opaque = acb;
> + acb->cancel_acb_save = save;
No need for this extra field. You can make a struct with {acb->cb,
acb->opaque, acb} and pass it as the opaque. You also do not need to
allocate it on the heap, since everything is synchronous.
> +
> + /* Use the synchronous version and hope our cb is called. */
> + acb->aiocb_info->cancel(acb);
Unfortunately, acb has been freed at this point, so you'll be accessing
a dangling pointer. I think you need to modify all cancel
implementations. For example:
- return whether they have called the callback
- only free the acb if they have called the callback
- otherwise, free the acb in bdrv_aio_cancel
Paolo
> + if (acb->cancel_acb_save) {
> + /* cb is not called yet, let's call it */
> + bdrv_aio_cancel_async_cb(acb->opaque, -ECANCELED);
> + }
> + }
> +}
> +
> /**************************************************************/
> /* async block device emulation */
>
> diff --git a/include/block/aio.h b/include/block/aio.h
> index c23de3c..fcc5c87 100644
> --- a/include/block/aio.h
> +++ b/include/block/aio.h
> @@ -27,6 +27,7 @@ typedef void BlockDriverCompletionFunc(void *opaque, int
> ret);
>
> typedef struct AIOCBInfo {
> void (*cancel)(BlockDriverAIOCB *acb);
> + void (*cancel_async)(BlockDriverAIOCB *acb);
> size_t aiocb_size;
> } AIOCBInfo;
>
> @@ -35,6 +36,7 @@ struct BlockDriverAIOCB {
> BlockDriverState *bs;
> BlockDriverCompletionFunc *cb;
> void *opaque;
> + BlockDriverAIOCB *cancel_acb_save;
> };