From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:42395) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Viomd-0008Sg-Ix for qemu-devel@nongnu.org; Tue, 19 Nov 2013 12:08:22 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ViomX-0002i5-Ip for qemu-devel@nongnu.org; Tue, 19 Nov 2013 12:08:15 -0500 Received: from mx1.redhat.com ([209.132.183.28]:49624) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ViomX-0002hp-Aa for qemu-devel@nongnu.org; Tue, 19 Nov 2013 12:08:09 -0500 From: Paolo Bonzini Date: Tue, 19 Nov 2013 18:07:29 +0100 Message-Id: <1384880863-10434-7-git-send-email-pbonzini@redhat.com> In-Reply-To: <1384880863-10434-1-git-send-email-pbonzini@redhat.com> References: <1384880863-10434-1-git-send-email-pbonzini@redhat.com> Subject: [Qemu-devel] [PATCH v2 06/20] block: make bdrv_co_do_write_zeroes stricter in producing aligned requests List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: kwolf@redhat.com, pl@kamp.de, stefanha@redhat.com Right now, bdrv_co_do_write_zeroes will only try to align the beginning of the request. However, it is simpler for many formats to expect the block layer to separate both the head *and* the tail. This makes sure that the format's bdrv_co_write_zeroes function will be called with aligned sector_num and nb_sectors for the bulk of the request. Signed-off-by: Paolo Bonzini --- block.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/block.c b/block.c index 4897649..567d669 100644 --- a/block.c +++ b/block.c @@ -2761,14 +2761,19 @@ static int coroutine_fn bdrv_co_do_write_zeroes(BlockDriverState *bs, while (nb_sectors > 0 && !ret) { int num = nb_sectors; - /* align request */ - if (bs->bl.write_zeroes_alignment && - num >= bs->bl.write_zeroes_alignment && - sector_num % bs->bl.write_zeroes_alignment) { - if (num > bs->bl.write_zeroes_alignment) { + /* Align request. Block drivers can expect the "bulk" of the request + * to be aligned. + */ + if (bs->bl.write_zeroes_alignment + && num > bs->bl.write_zeroes_alignment) { + if (sector_num % bs->bl.write_zeroes_alignment != 0) { + /* Make a small request up to the first aligned sector. */ num = bs->bl.write_zeroes_alignment; + num -= sector_num % bs->bl.write_zeroes_alignment; + } else if (num >= bs->bl.write_zeroes_alignment) { + /* Shorten the request to the last aligned sector. */ + num -= (sector_num + num) % bs->bl.write_zeroes_alignment; } - num -= sector_num % bs->bl.write_zeroes_alignment; } /* limit request size */ @@ -2785,24 +2790,27 @@ static int coroutine_fn bdrv_co_do_write_zeroes(BlockDriverState *bs, if (ret == -ENOTSUP) { /* Fall back to bounce buffer if write zeroes is unsupported */ iov.iov_len = num * BDRV_SECTOR_SIZE; if (iov.iov_base == NULL) { - /* allocate bounce buffer only once and ensure that it - * is big enough for this and all future requests. - */ - size_t bufsize = num <= nb_sectors ? num : max_write_zeroes; - iov.iov_base = qemu_blockalign(bs, bufsize * BDRV_SECTOR_SIZE); - memset(iov.iov_base, 0, bufsize * BDRV_SECTOR_SIZE); + iov.iov_base = qemu_blockalign(bs, num * BDRV_SECTOR_SIZE); + memset(iov.iov_base, 0, num * BDRV_SECTOR_SIZE); } qemu_iovec_init_external(&qiov, &iov, 1); ret = drv->bdrv_co_writev(bs, sector_num, num, &qiov); + if (num <= max_write_zeroes) { + /* Allocate bounce buffer only once if it is + * big enough for this and all future requests. + */ + qemu_vfree(iov.iov_base); + iov.iov_base = NULL; + } } sector_num += num; nb_sectors -= num; } qemu_vfree(iov.iov_base); return ret; } -- 1.8.4.2