From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([140.186.70.92]:40761) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1QTx4Q-0006hF-2F for qemu-devel@nongnu.org; Tue, 07 Jun 2011 10:15:54 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1QTx4M-0006nO-8c for qemu-devel@nongnu.org; Tue, 07 Jun 2011 10:15:49 -0400 Received: from mx1.redhat.com ([209.132.183.28]:58957) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1QTx4L-0006nE-Rp for qemu-devel@nongnu.org; Tue, 07 Jun 2011 10:15:46 -0400 Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id p57EFiXr027767 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Tue, 7 Jun 2011 10:15:44 -0400 From: Kevin Wolf Date: Tue, 7 Jun 2011 16:18:32 +0200 Message-Id: <1307456313-9884-3-git-send-email-kwolf@redhat.com> In-Reply-To: <1307456313-9884-1-git-send-email-kwolf@redhat.com> References: <1307456313-9884-1-git-send-email-kwolf@redhat.com> Subject: [Qemu-devel] [PATCH 2/3] qcow: Avoid direct AIO callback List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: kwolf@redhat.com, lcapitulino@redhat.com bdrv_aio_* must not call the callback before returning to its caller. In qcow, this could happen in some error cases. This starts the real requests processing in a BH to avoid this situation. Signed-off-by: Kevin Wolf --- block/qcow.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 files changed, 56 insertions(+), 2 deletions(-) diff --git a/block/qcow.c b/block/qcow.c index a26c886..227b104 100644 --- a/block/qcow.c +++ b/block/qcow.c @@ -496,6 +496,8 @@ typedef struct QCowAIOCB { uint64_t cluster_offset; uint8_t *cluster_data; struct iovec hd_iov; + bool is_write; + QEMUBH *bh; QEMUIOVector hd_qiov; BlockDriverAIOCB *hd_aiocb; } QCowAIOCB; @@ -525,6 +527,8 @@ static QCowAIOCB *qcow_aio_setup(BlockDriverState *bs, acb->hd_aiocb = NULL; acb->sector_num = sector_num; acb->qiov = qiov; + acb->is_write = is_write; + if (qiov->niov > 1) { acb->buf = acb->orig_buf = qemu_blockalign(bs, qiov->size); if (is_write) @@ -538,6 +542,38 @@ static QCowAIOCB *qcow_aio_setup(BlockDriverState *bs, return acb; } +static void qcow_aio_read_cb(void *opaque, int ret); +static void qcow_aio_write_cb(void *opaque, int ret); + +static void qcow_aio_rw_bh(void *opaque) +{ + QCowAIOCB *acb = opaque; + qemu_bh_delete(acb->bh); + acb->bh = NULL; + + if (acb->is_write) { + qcow_aio_write_cb(opaque, 0); + } else { + qcow_aio_read_cb(opaque, 0); + } +} + +static int qcow_schedule_bh(QEMUBHFunc *cb, QCowAIOCB *acb) +{ + if (acb->bh) { + return -EIO; + } + + acb->bh = qemu_bh_new(cb, acb); + if (!acb->bh) { + return -EIO; + } + + qemu_bh_schedule(acb->bh); + + return 0; +} + static void qcow_aio_read_cb(void *opaque, int ret) { QCowAIOCB *acb = opaque; @@ -640,12 +676,21 @@ static BlockDriverAIOCB *qcow_aio_readv(BlockDriverState *bs, BlockDriverCompletionFunc *cb, void *opaque) { QCowAIOCB *acb; + int ret; acb = qcow_aio_setup(bs, sector_num, qiov, nb_sectors, cb, opaque, 0); if (!acb) return NULL; - qcow_aio_read_cb(acb, 0); + ret = qcow_schedule_bh(qcow_aio_rw_bh, acb); + if (ret < 0) { + if (acb->qiov->niov > 1) { + qemu_vfree(acb->orig_buf); + } + qemu_aio_release(acb); + return NULL; + } + return &acb->common; } @@ -725,6 +770,7 @@ static BlockDriverAIOCB *qcow_aio_writev(BlockDriverState *bs, { BDRVQcowState *s = bs->opaque; QCowAIOCB *acb; + int ret; s->cluster_cache_offset = -1; /* disable compressed cache */ @@ -733,7 +779,15 @@ static BlockDriverAIOCB *qcow_aio_writev(BlockDriverState *bs, return NULL; - qcow_aio_write_cb(acb, 0); + ret = qcow_schedule_bh(qcow_aio_rw_bh, acb); + if (ret < 0) { + if (acb->qiov->niov > 1) { + qemu_vfree(acb->orig_buf); + } + qemu_aio_release(acb); + return NULL; + } + return &acb->common; } -- 1.7.5.2