From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:59387) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1W64Qm-0005nt-GM for qemu-devel@nongnu.org; Wed, 22 Jan 2014 15:29:53 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1W64Qh-00030q-Ex for qemu-devel@nongnu.org; Wed, 22 Jan 2014 15:29:48 -0500 Received: from paradis.irqsave.net ([62.212.105.220]:48088) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1W64Qg-00030V-VP for qemu-devel@nongnu.org; Wed, 22 Jan 2014 15:29:43 -0500 Date: Wed, 22 Jan 2014 21:29:39 +0100 From: =?iso-8859-1?Q?Beno=EEt?= Canet Message-ID: <20140122202939.GF3053@irqsave.net> References: <1389968119-24771-1-git-send-email-kwolf@redhat.com> <1389968119-24771-21-git-send-email-kwolf@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=iso-8859-1 Content-Disposition: inline In-Reply-To: <1389968119-24771-21-git-send-email-kwolf@redhat.com> Content-Transfer-Encoding: quoted-printable Subject: Re: [Qemu-devel] [PATCH v3 20/29] block: Align requests in bdrv_co_do_pwritev() List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: Kevin Wolf Cc: pl@kamp.de, qemu-devel@nongnu.org, mreitz@redhat.com, stefanha@redhat.com, pbonzini@redhat.com, xiawenc@linux.vnet.ibm.com Le Friday 17 Jan 2014 =E0 15:15:10 (+0100), Kevin Wolf a =E9crit : > This patch changes bdrv_co_do_pwritev() to actually be what its name > promises. If requests aren't properly aligned, it performs a RMW. >=20 > Requests touching the same block are serialised against the RMW request= . > Further optimisation of this is possible by differentiating types of > requests (concurrent reads should actually be okay here). >=20 > Signed-off-by: Kevin Wolf > Reviewed-by: Max Reitz > --- > block.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++= +++++++- > 1 file changed, 85 insertions(+), 1 deletion(-) >=20 > diff --git a/block.c b/block.c > index 55e8c69..859e1aa 100644 > --- a/block.c > +++ b/block.c > @@ -3055,6 +3055,12 @@ static int coroutine_fn bdrv_co_do_pwritev(Block= DriverState *bs, > BdrvRequestFlags flags) > { > BdrvTrackedRequest req; > + /* TODO Lift BDRV_SECTOR_SIZE restriction in BlockDriver interface= */ > + uint64_t align =3D MAX(BDRV_SECTOR_SIZE, bs->request_alignment); > + uint8_t *head_buf =3D NULL; > + uint8_t *tail_buf =3D NULL; > + QEMUIOVector local_qiov; > + bool use_local_qiov =3D false; > int ret; > =20 > if (!bs->drv) { > @@ -3073,10 +3079,88 @@ static int coroutine_fn bdrv_co_do_pwritev(Bloc= kDriverState *bs, > bdrv_io_limits_intercept(bs, bytes >> BDRV_SECTOR_BITS, true); > } > =20 > + /* > + * Align write if necessary by performing a read-modify-write cycl= e. > + * Pad qiov with the read parts and be sure to have a tracked requ= est not > + * only for bdrv_aligned_pwritev, but also for the reads of the RM= W cycle. > + */ > tracked_request_begin(&req, bs, offset, bytes, true); > - ret =3D bdrv_aligned_pwritev(bs, &req, offset, bytes, qiov, flags)= ; > + > + if (offset & (align - 1)) { > + QEMUIOVector head_qiov; > + struct iovec head_iov; > + > + mark_request_serialising(&req, align); > + wait_serialising_requests(&req); > + > + head_buf =3D qemu_blockalign(bs, align); > + head_iov =3D (struct iovec) { > + .iov_base =3D head_buf, > + .iov_len =3D align, > + }; > + qemu_iovec_init_external(&head_qiov, &head_iov, 1); > + > + ret =3D bdrv_aligned_preadv(bs, &req, offset & ~(align - 1), a= lign, > + align, &head_qiov, 0); > + if (ret < 0) { > + goto fail; > + } > + > + qemu_iovec_init(&local_qiov, qiov->niov + 2); > + qemu_iovec_add(&local_qiov, head_buf, offset & (align - 1)); > + qemu_iovec_concat(&local_qiov, qiov, 0, qiov->size); > + use_local_qiov =3D true; > + > + bytes +=3D offset & (align - 1); > + offset =3D offset & ~(align - 1); > + } > + > + if ((offset + bytes) & (align - 1)) { > + QEMUIOVector tail_qiov; > + struct iovec tail_iov; > + size_t tail_bytes; > + > + mark_request_serialising(&req, align); > + wait_serialising_requests(&req); > + > + tail_buf =3D qemu_blockalign(bs, align); > + tail_iov =3D (struct iovec) { > + .iov_base =3D tail_buf, > + .iov_len =3D align, > + }; > + qemu_iovec_init_external(&tail_qiov, &tail_iov, 1); > + > + ret =3D bdrv_aligned_preadv(bs, &req, (offset + bytes) & ~(ali= gn - 1), align, > + align, &tail_qiov, 0); > + if (ret < 0) { > + goto fail; > + } > + > + if (!use_local_qiov) { > + qemu_iovec_init(&local_qiov, qiov->niov + 1); > + qemu_iovec_concat(&local_qiov, qiov, 0, qiov->size); > + use_local_qiov =3D true; > + } > + > + tail_bytes =3D (offset + bytes) & (align - 1); > + qemu_iovec_add(&local_qiov, tail_buf + tail_bytes, align - tai= l_bytes); > + > + bytes =3D ROUND_UP(bytes, align); > + } > + > + ret =3D bdrv_aligned_pwritev(bs, &req, offset, bytes, > + use_local_qiov ? &local_qiov : qiov, > + flags); > + > +fail: > tracked_request_end(&req); > =20 > + if (use_local_qiov) { > + qemu_iovec_destroy(&local_qiov); > + qemu_vfree(head_buf); > + qemu_vfree(tail_buf); > + } > + > return ret; > } > =20 > --=20 > 1.8.1.4 >=20 >=20 Reviewed-by: Benoit Canet