From nobody Tue Nov 18 09:17:06 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org ARC-Seal: i=1; a=rsa-sha256; t=1609087785; cv=none; d=zohomail.com; s=zohoarc; b=KgDAqLoNhT7fDZz8G+VYlFom/B9l1xEdzcncacOvG1VEO98UZqLzIWzPQ6qGsLLNASXxB3jeieFOHT1e5jOsfk+RXadMrtbl/m+KkelyAD5qiFRr6BIb6L8RLN/CKwC/y8nMrPej1oGe1ODnvYAFx+tvRvSC37EKltS258HxjkU= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1609087785; h=Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:Message-ID:References:Sender:Subject:To; bh=zIIpumr0xv/Kf2BMmF1gRrQIzyGb80n4Ou3kfjmZ16Y=; b=NiDfUb104ay4a5P/ma5o9OscYiDkpoRzWYDW3hklVQdAhd5QJL/CMRwEXEEvNMsTe37GWvAZTlZe91rYPOKtLdzotft+idolw2Hf/8Ad4b3XNQhCUmyhE/1Ajrijxm90yE8vcWSHBsXLS75FJy0cXiaI8YGmZdm+Fiu1Xs3tPuI= ARC-Authentication-Results: i=1; mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1609087785522413.02605116150846; Sun, 27 Dec 2020 08:49:45 -0800 (PST) Received: from localhost ([::1]:38630 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ktZEm-0007cs-He for importer@patchew.org; Sun, 27 Dec 2020 11:49:44 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:43322) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ktZ8I-0001VD-Mg for qemu-devel@nongnu.org; Sun, 27 Dec 2020 11:43:02 -0500 Received: from kerio.kamp.de ([195.62.97.192]:33908) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ktZ8G-0003ya-DK for qemu-devel@nongnu.org; Sun, 27 Dec 2020 11:43:02 -0500 Received: from submission.kamp.de ([195.62.97.28]) by kerio.kamp.de with ESMTPS (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256 bits)) for qemu-devel@nongnu.org; Sun, 27 Dec 2020 17:42:42 +0100 Received: (qmail 22358 invoked from network); 27 Dec 2020 16:42:44 -0000 Received: from lieven-pc.kamp-intra.net (HELO lieven-pc) (relay@kamp.de@::ffff:172.21.12.60) by submission.kamp.de with ESMTPS (DHE-RSA-AES256-GCM-SHA384 encrypted) ESMTPA; 27 Dec 2020 16:42:44 -0000 Received: by lieven-pc (Postfix, from userid 1060) id 6251313DD26; Sun, 27 Dec 2020 17:42:44 +0100 (CET) X-Footer: a2FtcC5kZQ== From: Peter Lieven To: qemu-block@nongnu.org Subject: [PATCH 5/7] block/rbd: migrate from aio to coroutines Date: Sun, 27 Dec 2020 17:42:34 +0100 Message-Id: <20201227164236.10143-6-pl@kamp.de> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20201227164236.10143-1-pl@kamp.de> References: <20201227164236.10143-1-pl@kamp.de> Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=195.62.97.192; envelope-from=pl@kamp.de; helo=kerio.kamp.de X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kwolf@redhat.com, Peter Lieven , qemu-devel@nongnu.org, ct@flyingcircus.io, mreitz@redhat.com, dillaman@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Signed-off-by: Peter Lieven --- block/rbd.c | 247 ++++++++++++++++++---------------------------------- 1 file changed, 84 insertions(+), 163 deletions(-) diff --git a/block/rbd.c b/block/rbd.c index 27b232f4d8..2d77d0007f 100644 --- a/block/rbd.c +++ b/block/rbd.c @@ -66,22 +66,6 @@ typedef enum { RBD_AIO_FLUSH } RBDAIOCmd; =20 -typedef struct RBDAIOCB { - BlockAIOCB common; - int64_t ret; - QEMUIOVector *qiov; - RBDAIOCmd cmd; - int error; - struct BDRVRBDState *s; -} RBDAIOCB; - -typedef struct RADOSCB { - RBDAIOCB *acb; - struct BDRVRBDState *s; - int64_t size; - int64_t ret; -} RADOSCB; - typedef struct BDRVRBDState { rados_t cluster; rados_ioctx_t io_ctx; @@ -94,6 +78,13 @@ typedef struct BDRVRBDState { AioContext *aio_context; } BDRVRBDState; =20 +typedef struct RBDTask { + BDRVRBDState *s; + Coroutine *co; + bool complete; + int64_t ret; +} RBDTask; + static int qemu_rbd_connect(rados_t *cluster, rados_ioctx_t *io_ctx, BlockdevOptionsRbd *opts, bool cache, const char *keypairs, const char *secretid, @@ -316,13 +307,6 @@ static int qemu_rbd_set_keypairs(rados_t cluster, cons= t char *keypairs_json, return ret; } =20 -static void qemu_rbd_memset(RADOSCB *rcb, int64_t offs) -{ - RBDAIOCB *acb =3D rcb->acb; - iov_memset(acb->qiov->iov, acb->qiov->niov, offs, 0, - acb->qiov->size - offs); -} - /* FIXME Deprecate and remove keypairs or make it available in QMP. */ static int qemu_rbd_do_create(BlockdevCreateOptions *options, const char *keypairs, const char *password_s= ecret, @@ -440,46 +424,6 @@ exit: return ret; } =20 -/* - * This aio completion is being called from rbd_finish_bh() and runs in qe= mu - * BH context. - */ -static void qemu_rbd_complete_aio(RADOSCB *rcb) -{ - RBDAIOCB *acb =3D rcb->acb; - int64_t r; - - r =3D rcb->ret; - - if (acb->cmd !=3D RBD_AIO_READ) { - if (r < 0) { - acb->ret =3D r; - acb->error =3D 1; - } else if (!acb->error) { - acb->ret =3D rcb->size; - } - } else { - if (r < 0) { - qemu_rbd_memset(rcb, 0); - acb->ret =3D r; - acb->error =3D 1; - } else if (r < rcb->size) { - qemu_rbd_memset(rcb, r); - if (!acb->error) { - acb->ret =3D rcb->size; - } - } else if (!acb->error) { - acb->ret =3D r; - } - } - - g_free(rcb); - - acb->common.cb(acb->common.opaque, (acb->ret > 0 ? 0 : acb->ret)); - - qemu_aio_unref(acb); -} - static char *qemu_rbd_mon_host(BlockdevOptionsRbd *opts, Error **errp) { const char **vals; @@ -817,88 +761,49 @@ static int qemu_rbd_resize(BlockDriverState *bs, uint= 64_t size) return 0; } =20 -static const AIOCBInfo rbd_aiocb_info =3D { - .aiocb_size =3D sizeof(RBDAIOCB), -}; - -static void rbd_finish_bh(void *opaque) +static void qemu_rbd_finish_bh(void *opaque) { - RADOSCB *rcb =3D opaque; - qemu_rbd_complete_aio(rcb); + RBDTask *task =3D opaque; + task->complete =3D 1; + aio_co_wake(task->co); } =20 -/* - * This is the callback function for rbd_aio_read and _write - * - * Note: this function is being called from a non qemu thread so - * we need to be careful about what we do here. Generally we only - * schedule a BH, and do the rest of the io completion handling - * from rbd_finish_bh() which runs in a qemu context. - */ -static void rbd_finish_aiocb(rbd_completion_t c, RADOSCB *rcb) +static void qemu_rbd_completion_cb(rbd_completion_t c, RBDTask *task) { - RBDAIOCB *acb =3D rcb->acb; - - rcb->ret =3D rbd_aio_get_return_value(c); + task->ret =3D rbd_aio_get_return_value(c); rbd_aio_release(c); - - replay_bh_schedule_oneshot_event(acb->s->aio_context, rbd_finish_bh, r= cb); + aio_bh_schedule_oneshot(task->s->aio_context, qemu_rbd_finish_bh, task= ); } =20 -static BlockAIOCB *rbd_start_aio(BlockDriverState *bs, - int64_t off, - QEMUIOVector *qiov, - int64_t size, - BlockCompletionFunc *cb, - void *opaque, - RBDAIOCmd cmd) +static int coroutine_fn qemu_rbd_start_co(BlockDriverState *bs, + uint64_t offset, + uint64_t bytes, + QEMUIOVector *qiov, + int flags, + RBDAIOCmd cmd) { - RBDAIOCB *acb; - RADOSCB *rcb =3D NULL; - rbd_completion_t c; - int r; - BDRVRBDState *s =3D bs->opaque; + RBDTask task =3D { .s =3D s, .co =3D qemu_coroutine_self() }; + rbd_completion_t c; + int r, ret =3D -EIO; =20 - acb =3D qemu_aio_get(&rbd_aiocb_info, bs, cb, opaque); - acb->cmd =3D cmd; - acb->qiov =3D qiov; - assert(!qiov || qiov->size =3D=3D size); - - rcb =3D g_new(RADOSCB, 1); - - acb->ret =3D 0; - acb->error =3D 0; - acb->s =3D s; + assert(!qiov || qiov->size =3D=3D bytes); =20 - rcb->acb =3D acb; - rcb->s =3D acb->s; - rcb->size =3D size; - r =3D rbd_aio_create_completion(rcb, (rbd_callback_t) rbd_finish_aiocb= , &c); + r =3D rbd_aio_create_completion(&task, + (rbd_callback_t) qemu_rbd_completion_cb,= &c); if (r < 0) { goto failed; } =20 switch (cmd) { - case RBD_AIO_WRITE: - /* - * RBD APIs don't allow us to write more than actual size, so in o= rder - * to support growing images, we resize the image before write - * operations that exceed the current size. - */ - if (off + size > s->image_size) { - r =3D qemu_rbd_resize(bs, off + size); - if (r < 0) { - goto failed_completion; - } - } - r =3D rbd_aio_writev(s->image, qiov->iov, qiov->niov, off, c); - break; case RBD_AIO_READ: - r =3D rbd_aio_readv(s->image, qiov->iov, qiov->niov, off, c); + r =3D rbd_aio_readv(s->image, qiov->iov, qiov->niov, offset, c); + break; + case RBD_AIO_WRITE: + r =3D rbd_aio_writev(s->image, qiov->iov, qiov->niov, offset, c); break; case RBD_AIO_DISCARD: - r =3D rbd_aio_discard(s->image, off, size, c); + r =3D rbd_aio_discard(s->image, offset, bytes, c); break; case RBD_AIO_FLUSH: r =3D rbd_aio_flush(s->image, c); @@ -908,44 +813,71 @@ static BlockAIOCB *rbd_start_aio(BlockDriverState *bs, } =20 if (r < 0) { + task.complete =3D 1; + task.ret =3D r; + } + + while (!task.complete) { + qemu_coroutine_yield(); + } + + if (task.ret < 0) { + error_report("rbd request failed: cmd %d offset %" PRIu64 " bytes = %" + PRIu64 " flags %d task.ret %" PRIi64 " (%s)", cmd, of= fset, + bytes, flags, task.ret, strerror(-task.ret)); goto failed_completion; } - return &acb->common; + + /* zero pad short reads */ + if (cmd =3D=3D RBD_AIO_READ && task.ret < qiov->size) { + qemu_iovec_memset(qiov, task.ret, 0, qiov->size - task.ret); + } + + return 0; =20 failed_completion: rbd_aio_release(c); failed: - g_free(rcb); + return ret; +} =20 - qemu_aio_unref(acb); - return NULL; +static int +coroutine_fn qemu_rbd_co_preadv(BlockDriverState *bs, uint64_t offset, + uint64_t bytes, QEMUIOVector *qiov, + int flags) +{ + return qemu_rbd_start_co(bs, offset, bytes, qiov, flags, RBD_AIO_READ); } =20 -static BlockAIOCB *qemu_rbd_aio_preadv(BlockDriverState *bs, - uint64_t offset, uint64_t bytes, - QEMUIOVector *qiov, int flags, - BlockCompletionFunc *cb, - void *opaque) +static int +coroutine_fn qemu_rbd_co_pwritev(BlockDriverState *bs, uint64_t offset, + uint64_t bytes, QEMUIOVector *qiov, + int flags) { - return rbd_start_aio(bs, offset, qiov, bytes, cb, opaque, - RBD_AIO_READ); + BDRVRBDState *s =3D bs->opaque; + /* + * RBD APIs don't allow us to write more than actual size, so in order + * to support growing images, we resize the image before write + * operations that exceed the current size. + */ + if (offset + bytes > s->image_size) { + int r =3D qemu_rbd_resize(bs, offset + bytes); + if (r < 0) { + return r; + } + } + return qemu_rbd_start_co(bs, offset, bytes, qiov, flags, RBD_AIO_WRITE= ); } =20 -static BlockAIOCB *qemu_rbd_aio_pwritev(BlockDriverState *bs, - uint64_t offset, uint64_t bytes, - QEMUIOVector *qiov, int flags, - BlockCompletionFunc *cb, - void *opaque) +static int coroutine_fn qemu_rbd_co_flush(BlockDriverState *bs) { - return rbd_start_aio(bs, offset, qiov, bytes, cb, opaque, - RBD_AIO_WRITE); + return qemu_rbd_start_co(bs, 0, 0, NULL, 0, RBD_AIO_FLUSH); } =20 -static BlockAIOCB *qemu_rbd_aio_flush(BlockDriverState *bs, - BlockCompletionFunc *cb, - void *opaque) +static int coroutine_fn qemu_rbd_co_pdiscard(BlockDriverState *bs, + int64_t offset, int count) { - return rbd_start_aio(bs, 0, NULL, 0, cb, opaque, RBD_AIO_FLUSH); + return qemu_rbd_start_co(bs, offset, count, NULL, 0, RBD_AIO_DISCARD); } =20 static int qemu_rbd_getinfo(BlockDriverState *bs, BlockDriverInfo *bdi) @@ -1097,16 +1029,6 @@ static int qemu_rbd_snap_list(BlockDriverState *bs, return snap_count; } =20 -static BlockAIOCB *qemu_rbd_aio_pdiscard(BlockDriverState *bs, - int64_t offset, - int bytes, - BlockCompletionFunc *cb, - void *opaque) -{ - return rbd_start_aio(bs, offset, NULL, bytes, cb, opaque, - RBD_AIO_DISCARD); -} - static void coroutine_fn qemu_rbd_co_invalidate_cache(BlockDriverState *bs, Error **errp) { @@ -1182,11 +1104,10 @@ static BlockDriver bdrv_rbd =3D { .bdrv_co_truncate =3D qemu_rbd_co_truncate, .protocol_name =3D "rbd", =20 - .bdrv_aio_preadv =3D qemu_rbd_aio_preadv, - .bdrv_aio_pwritev =3D qemu_rbd_aio_pwritev, - - .bdrv_aio_flush =3D qemu_rbd_aio_flush, - .bdrv_aio_pdiscard =3D qemu_rbd_aio_pdiscard, + .bdrv_co_preadv =3D qemu_rbd_co_preadv, + .bdrv_co_pwritev =3D qemu_rbd_co_pwritev, + .bdrv_co_flush_to_disk =3D qemu_rbd_co_flush, + .bdrv_co_pdiscard =3D qemu_rbd_co_pdiscard, =20 .bdrv_snapshot_create =3D qemu_rbd_snap_create, .bdrv_snapshot_delete =3D qemu_rbd_snap_remove, --=20 2.17.1