From nobody Fri May 17 18:58:11 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1530023243070755.3118408968518; Tue, 26 Jun 2018 07:27:23 -0700 (PDT) Received: from localhost ([::1]:53045 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fXowD-0003Y6-OX for importer@patchew.org; Tue, 26 Jun 2018 10:27:21 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:42837) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fXoti-0001op-IK for qemu-devel@nongnu.org; Tue, 26 Jun 2018 10:24:47 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fXoth-00031a-Jp for qemu-devel@nongnu.org; Tue, 26 Jun 2018 10:24:46 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:39828 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fXotd-0002jD-Fu; Tue, 26 Jun 2018 10:24:41 -0400 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.rdu2.redhat.com [10.11.54.3]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 24A5B81A4EAD; Tue, 26 Jun 2018 14:24:41 +0000 (UTC) Received: from dhcp-200-186.str.redhat.com (dhcp-200-186.str.redhat.com [10.33.200.186]) by smtp.corp.redhat.com (Postfix) with ESMTP id 3EBB11117634; Tue, 26 Jun 2018 14:24:40 +0000 (UTC) From: Kevin Wolf To: qemu-block@nongnu.org Date: Tue, 26 Jun 2018 16:24:29 +0200 Message-Id: <20180626142434.22090-2-kwolf@redhat.com> In-Reply-To: <20180626142434.22090-1-kwolf@redhat.com> References: <20180626142434.22090-1-kwolf@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.3 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.8]); Tue, 26 Jun 2018 14:24:41 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.8]); Tue, 26 Jun 2018 14:24:41 +0000 (UTC) for IP:'10.11.54.3' DOMAIN:'int-mx03.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'kwolf@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PATCH v2 1/6] qcow2: Fix qcow2_truncate() error return value X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kwolf@redhat.com, qemu-devel@nongnu.org, stefanha@redhat.com, mreitz@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" If qcow2_alloc_clusters_at() returns an error, we do need to negate it to get back the positive errno code for error_setg_errno(), but we still need to return the negative error code. Fixes: 772d1f973f87269f6a4a4ea4b880680f3779bbdf Signed-off-by: Kevin Wolf Reviewed-by: Stefan Hajnoczi --- block/qcow2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/block/qcow2.c b/block/qcow2.c index a3a3aa2a97..6b2e1e1058 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -3597,7 +3597,7 @@ static int qcow2_truncate(BlockDriverState *bs, int64= _t offset, if (clusters_allocated < 0) { error_setg_errno(errp, -clusters_allocated, "Failed to allocate data clusters"); - return -clusters_allocated; + return clusters_allocated; } =20 assert(clusters_allocated =3D=3D nb_new_data_clusters); --=20 2.13.6 From nobody Fri May 17 18:58:11 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 153002339557110.053978973202902; Tue, 26 Jun 2018 07:29:55 -0700 (PDT) Received: from localhost ([::1]:53059 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fXoyc-0005iB-NM for importer@patchew.org; Tue, 26 Jun 2018 10:29:50 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:42971) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fXotr-0001z4-GA for qemu-devel@nongnu.org; Tue, 26 Jun 2018 10:24:59 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fXotn-0003VB-Dn for qemu-devel@nongnu.org; Tue, 26 Jun 2018 10:24:55 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:53998 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fXote-0002ph-TP; Tue, 26 Jun 2018 10:24:43 -0400 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.rdu2.redhat.com [10.11.54.3]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 84BB687AC7; Tue, 26 Jun 2018 14:24:42 +0000 (UTC) Received: from dhcp-200-186.str.redhat.com (dhcp-200-186.str.redhat.com [10.33.200.186]) by smtp.corp.redhat.com (Postfix) with ESMTP id 5E9241117634; Tue, 26 Jun 2018 14:24:41 +0000 (UTC) From: Kevin Wolf To: qemu-block@nongnu.org Date: Tue, 26 Jun 2018 16:24:30 +0200 Message-Id: <20180626142434.22090-3-kwolf@redhat.com> In-Reply-To: <20180626142434.22090-1-kwolf@redhat.com> References: <20180626142434.22090-1-kwolf@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.3 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.1]); Tue, 26 Jun 2018 14:24:42 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.1]); Tue, 26 Jun 2018 14:24:42 +0000 (UTC) for IP:'10.11.54.3' DOMAIN:'int-mx03.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'kwolf@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PATCH v2 2/6] block: Convert .bdrv_truncate callback to coroutine_fn X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kwolf@redhat.com, qemu-devel@nongnu.org, stefanha@redhat.com, mreitz@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" bdrv_truncate() is an operation that can block (even for a quite long time, depending on the PreallocMode) in I/O paths that shouldn't block. Convert it to a coroutine_fn so that we have the infrastructure for drivers to make their .bdrv_co_truncate implementation asynchronous. This change could potentially introduce new race conditions because bdrv_truncate() isn't necessarily executed atomically any more. Whether this is a problem needs to be evaluated for each block driver that supports truncate: * file-posix/win32, gluster, iscsi, nfs, rbd, ssh, sheepdog: The protocol drivers are trivially safe because they don't actually yield yet, so there is no change in behaviour. * copy-on-read, crypto, raw-format: Essentially just filter drivers that pass the request to a child node, no problem. * qcow2: The implementation modifies metadata, so it needs to hold s->lock to be safe with concurrent I/O requests. In order to avoid double locking, this requires pulling the locking out into preallocate_co() and using qcow2_write_caches() instead of bdrv_flush(). * qed: Does a single header update, this is fine without locking. Signed-off-by: Kevin Wolf Reviewed-by: Stefan Hajnoczi --- include/block/block.h | 4 +++ include/block/block_int.h | 4 +-- block.c | 63 ++++++++++++++++++++++++++++++++++------ block/copy-on-read.c | 8 +++--- block/crypto.c | 9 +++--- block/file-posix.c | 12 ++++---- block/file-win32.c | 6 ++-- block/gluster.c | 14 +++++---- block/iscsi.c | 8 +++--- block/nfs.c | 7 +++-- block/qcow2.c | 73 ++++++++++++++++++++++++++++---------------= ---- block/qed.c | 8 ++++-- block/raw-format.c | 8 +++--- block/rbd.c | 8 ++++-- block/sheepdog.c | 12 ++++---- block/ssh.c | 6 ++-- 16 files changed, 161 insertions(+), 89 deletions(-) diff --git a/include/block/block.h b/include/block/block.h index b1d6fdb97a..42e59ff585 100644 --- a/include/block/block.h +++ b/include/block/block.h @@ -300,8 +300,12 @@ int coroutine_fn bdrv_co_pwrite_zeroes(BdrvChild *chil= d, int64_t offset, BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs, const char *backing_file); void bdrv_refresh_filename(BlockDriverState *bs); + +int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, + PreallocMode prealloc, Error **errp); int bdrv_truncate(BdrvChild *child, int64_t offset, PreallocMode prealloc, Error **errp); + int64_t bdrv_nb_sectors(BlockDriverState *bs); int64_t bdrv_getlength(BlockDriverState *bs); int64_t bdrv_get_allocated_file_size(BlockDriverState *bs); diff --git a/include/block/block_int.h b/include/block/block_int.h index 74646ed722..c653ee663a 100644 --- a/include/block/block_int.h +++ b/include/block/block_int.h @@ -289,8 +289,8 @@ struct BlockDriver { * bdrv_parse_filename. */ const char *protocol_name; - int (*bdrv_truncate)(BlockDriverState *bs, int64_t offset, - PreallocMode prealloc, Error **errp); + int coroutine_fn (*bdrv_co_truncate)(BlockDriverState *bs, int64_t off= set, + PreallocMode prealloc, Error **er= rp); =20 int64_t (*bdrv_getlength)(BlockDriverState *bs); bool has_variable_length; diff --git a/block.c b/block.c index 1b8147c1b3..f761bc85d5 100644 --- a/block.c +++ b/block.c @@ -3788,8 +3788,8 @@ exit: /** * Truncate file to 'offset' bytes (needed only for file protocols) */ -int bdrv_truncate(BdrvChild *child, int64_t offset, PreallocMode prealloc, - Error **errp) +int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, + PreallocMode prealloc, Error **errp) { BlockDriverState *bs =3D child->bs; BlockDriver *drv =3D bs->drv; @@ -3807,23 +3807,28 @@ int bdrv_truncate(BdrvChild *child, int64_t offset,= PreallocMode prealloc, return -EINVAL; } =20 - if (!drv->bdrv_truncate) { + bdrv_inc_in_flight(bs); + + if (!drv->bdrv_co_truncate) { if (bs->file && drv->is_filter) { - return bdrv_truncate(bs->file, offset, prealloc, errp); + ret =3D bdrv_co_truncate(bs->file, offset, prealloc, errp); + goto out; } error_setg(errp, "Image format driver does not support resize"); - return -ENOTSUP; + ret =3D -ENOTSUP; + goto out; } if (bs->read_only) { error_setg(errp, "Image is read-only"); - return -EACCES; + ret =3D -EACCES; + goto out; } =20 assert(!(bs->open_flags & BDRV_O_INACTIVE)); =20 - ret =3D drv->bdrv_truncate(bs, offset, prealloc, errp); + ret =3D drv->bdrv_co_truncate(bs, offset, prealloc, errp); if (ret < 0) { - return ret; + goto out; } ret =3D refresh_total_sectors(bs, offset >> BDRV_SECTOR_BITS); if (ret < 0) { @@ -3834,9 +3839,51 @@ int bdrv_truncate(BdrvChild *child, int64_t offset, = PreallocMode prealloc, bdrv_dirty_bitmap_truncate(bs, offset); bdrv_parent_cb_resize(bs); atomic_inc(&bs->write_gen); + +out: + bdrv_dec_in_flight(bs); return ret; } =20 +typedef struct TruncateCo { + BdrvChild *child; + int64_t offset; + PreallocMode prealloc; + Error **errp; + int ret; +} TruncateCo; + +static void coroutine_fn bdrv_truncate_co_entry(void *opaque) +{ + TruncateCo *tco =3D opaque; + tco->ret =3D bdrv_co_truncate(tco->child, tco->offset, tco->prealloc, + tco->errp); +} + +int bdrv_truncate(BdrvChild *child, int64_t offset, PreallocMode prealloc, + Error **errp) +{ + Coroutine *co; + TruncateCo tco =3D { + .child =3D child, + .offset =3D offset, + .prealloc =3D prealloc, + .errp =3D errp, + .ret =3D NOT_DONE, + }; + + if (qemu_in_coroutine()) { + /* Fast-path if already in coroutine context */ + bdrv_truncate_co_entry(&tco); + } else { + co =3D qemu_coroutine_create(bdrv_truncate_co_entry, &tco); + qemu_coroutine_enter(co); + BDRV_POLL_WHILE(child->bs, tco.ret =3D=3D NOT_DONE); + } + + return tco.ret; +} + /** * Length of a allocated file in bytes. Sparse files are counted by actual * allocated space. Return < 0 if error or unknown. diff --git a/block/copy-on-read.c b/block/copy-on-read.c index 6a97208888..1dcdaeed69 100644 --- a/block/copy-on-read.c +++ b/block/copy-on-read.c @@ -80,10 +80,10 @@ static int64_t cor_getlength(BlockDriverState *bs) } =20 =20 -static int cor_truncate(BlockDriverState *bs, int64_t offset, - PreallocMode prealloc, Error **errp) +static int coroutine_fn cor_co_truncate(BlockDriverState *bs, int64_t offs= et, + PreallocMode prealloc, Error **err= p) { - return bdrv_truncate(bs->file, offset, prealloc, errp); + return bdrv_co_truncate(bs->file, offset, prealloc, errp); } =20 =20 @@ -147,7 +147,7 @@ BlockDriver bdrv_copy_on_read =3D { .bdrv_child_perm =3D cor_child_perm, =20 .bdrv_getlength =3D cor_getlength, - .bdrv_truncate =3D cor_truncate, + .bdrv_co_truncate =3D cor_co_truncate, =20 .bdrv_co_preadv =3D cor_co_preadv, .bdrv_co_pwritev =3D cor_co_pwritev, diff --git a/block/crypto.c b/block/crypto.c index aaa8fb7530..210c80d5c7 100644 --- a/block/crypto.c +++ b/block/crypto.c @@ -357,8 +357,9 @@ static int block_crypto_co_create_generic(BlockDriverSt= ate *bs, return ret; } =20 -static int block_crypto_truncate(BlockDriverState *bs, int64_t offset, - PreallocMode prealloc, Error **errp) +static int coroutine_fn +block_crypto_co_truncate(BlockDriverState *bs, int64_t offset, + PreallocMode prealloc, Error **errp) { BlockCrypto *crypto =3D bs->opaque; uint64_t payload_offset =3D @@ -371,7 +372,7 @@ static int block_crypto_truncate(BlockDriverState *bs, = int64_t offset, =20 offset +=3D payload_offset; =20 - return bdrv_truncate(bs->file, offset, prealloc, errp); + return bdrv_co_truncate(bs->file, offset, prealloc, errp); } =20 static void block_crypto_close(BlockDriverState *bs) @@ -700,7 +701,7 @@ BlockDriver bdrv_crypto_luks =3D { .bdrv_child_perm =3D bdrv_format_default_perms, .bdrv_co_create =3D block_crypto_co_create_luks, .bdrv_co_create_opts =3D block_crypto_co_create_opts_luks, - .bdrv_truncate =3D block_crypto_truncate, + .bdrv_co_truncate =3D block_crypto_co_truncate, .create_opts =3D &block_crypto_create_opts_luks, =20 .bdrv_reopen_prepare =3D block_crypto_reopen_prepare, diff --git a/block/file-posix.c b/block/file-posix.c index 07bb061fe4..6223a8bccc 100644 --- a/block/file-posix.c +++ b/block/file-posix.c @@ -1856,8 +1856,8 @@ out: return result; } =20 -static int raw_truncate(BlockDriverState *bs, int64_t offset, - PreallocMode prealloc, Error **errp) +static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offs= et, + PreallocMode prealloc, Error **err= p) { BDRVRawState *s =3D bs->opaque; struct stat st; @@ -2602,7 +2602,7 @@ BlockDriver bdrv_file =3D { .bdrv_io_plug =3D raw_aio_plug, .bdrv_io_unplug =3D raw_aio_unplug, =20 - .bdrv_truncate =3D raw_truncate, + .bdrv_co_truncate =3D raw_co_truncate, .bdrv_getlength =3D raw_getlength, .bdrv_get_info =3D raw_get_info, .bdrv_get_allocated_file_size @@ -3082,7 +3082,7 @@ static BlockDriver bdrv_host_device =3D { .bdrv_io_plug =3D raw_aio_plug, .bdrv_io_unplug =3D raw_aio_unplug, =20 - .bdrv_truncate =3D raw_truncate, + .bdrv_co_truncate =3D raw_co_truncate, .bdrv_getlength =3D raw_getlength, .bdrv_get_info =3D raw_get_info, .bdrv_get_allocated_file_size @@ -3204,7 +3204,7 @@ static BlockDriver bdrv_host_cdrom =3D { .bdrv_io_plug =3D raw_aio_plug, .bdrv_io_unplug =3D raw_aio_unplug, =20 - .bdrv_truncate =3D raw_truncate, + .bdrv_co_truncate =3D raw_co_truncate, .bdrv_getlength =3D raw_getlength, .has_variable_length =3D true, .bdrv_get_allocated_file_size @@ -3334,7 +3334,7 @@ static BlockDriver bdrv_host_cdrom =3D { .bdrv_io_plug =3D raw_aio_plug, .bdrv_io_unplug =3D raw_aio_unplug, =20 - .bdrv_truncate =3D raw_truncate, + .bdrv_co_truncate =3D raw_co_truncate, .bdrv_getlength =3D raw_getlength, .has_variable_length =3D true, .bdrv_get_allocated_file_size diff --git a/block/file-win32.c b/block/file-win32.c index 3c67db4336..0411fe80fd 100644 --- a/block/file-win32.c +++ b/block/file-win32.c @@ -467,8 +467,8 @@ static void raw_close(BlockDriverState *bs) } } =20 -static int raw_truncate(BlockDriverState *bs, int64_t offset, - PreallocMode prealloc, Error **errp) +static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offs= et, + PreallocMode prealloc, Error **err= p) { BDRVRawState *s =3D bs->opaque; LONG low, high; @@ -640,7 +640,7 @@ BlockDriver bdrv_file =3D { .bdrv_aio_pwritev =3D raw_aio_pwritev, .bdrv_aio_flush =3D raw_aio_flush, =20 - .bdrv_truncate =3D raw_truncate, + .bdrv_co_truncate =3D raw_co_truncate, .bdrv_getlength =3D raw_getlength, .bdrv_get_allocated_file_size =3D raw_get_allocated_file_size, diff --git a/block/gluster.c b/block/gluster.c index b5fe7f3e87..a4e1c8ecd8 100644 --- a/block/gluster.c +++ b/block/gluster.c @@ -1177,8 +1177,10 @@ static coroutine_fn int qemu_gluster_co_rw(BlockDriv= erState *bs, return acb.ret; } =20 -static int qemu_gluster_truncate(BlockDriverState *bs, int64_t offset, - PreallocMode prealloc, Error **errp) +static coroutine_fn int qemu_gluster_co_truncate(BlockDriverState *bs, + int64_t offset, + PreallocMode prealloc, + Error **errp) { BDRVGlusterState *s =3D bs->opaque; return qemu_gluster_do_truncate(s->fd, offset, prealloc, errp); @@ -1499,7 +1501,7 @@ static BlockDriver bdrv_gluster =3D { .bdrv_co_create_opts =3D qemu_gluster_co_create_opts, .bdrv_getlength =3D qemu_gluster_getlength, .bdrv_get_allocated_file_size =3D qemu_gluster_allocated_file_size, - .bdrv_truncate =3D qemu_gluster_truncate, + .bdrv_co_truncate =3D qemu_gluster_co_truncate, .bdrv_co_readv =3D qemu_gluster_co_readv, .bdrv_co_writev =3D qemu_gluster_co_writev, .bdrv_co_flush_to_disk =3D qemu_gluster_co_flush_to_disk, @@ -1528,7 +1530,7 @@ static BlockDriver bdrv_gluster_tcp =3D { .bdrv_co_create_opts =3D qemu_gluster_co_create_opts, .bdrv_getlength =3D qemu_gluster_getlength, .bdrv_get_allocated_file_size =3D qemu_gluster_allocated_file_size, - .bdrv_truncate =3D qemu_gluster_truncate, + .bdrv_co_truncate =3D qemu_gluster_co_truncate, .bdrv_co_readv =3D qemu_gluster_co_readv, .bdrv_co_writev =3D qemu_gluster_co_writev, .bdrv_co_flush_to_disk =3D qemu_gluster_co_flush_to_disk, @@ -1557,7 +1559,7 @@ static BlockDriver bdrv_gluster_unix =3D { .bdrv_co_create_opts =3D qemu_gluster_co_create_opts, .bdrv_getlength =3D qemu_gluster_getlength, .bdrv_get_allocated_file_size =3D qemu_gluster_allocated_file_size, - .bdrv_truncate =3D qemu_gluster_truncate, + .bdrv_co_truncate =3D qemu_gluster_co_truncate, .bdrv_co_readv =3D qemu_gluster_co_readv, .bdrv_co_writev =3D qemu_gluster_co_writev, .bdrv_co_flush_to_disk =3D qemu_gluster_co_flush_to_disk, @@ -1592,7 +1594,7 @@ static BlockDriver bdrv_gluster_rdma =3D { .bdrv_co_create_opts =3D qemu_gluster_co_create_opts, .bdrv_getlength =3D qemu_gluster_getlength, .bdrv_get_allocated_file_size =3D qemu_gluster_allocated_file_size, - .bdrv_truncate =3D qemu_gluster_truncate, + .bdrv_co_truncate =3D qemu_gluster_co_truncate, .bdrv_co_readv =3D qemu_gluster_co_readv, .bdrv_co_writev =3D qemu_gluster_co_writev, .bdrv_co_flush_to_disk =3D qemu_gluster_co_flush_to_disk, diff --git a/block/iscsi.c b/block/iscsi.c index 9f00fb47a5..bc84b14e20 100644 --- a/block/iscsi.c +++ b/block/iscsi.c @@ -2085,8 +2085,8 @@ static void iscsi_reopen_commit(BDRVReopenState *reop= en_state) } } =20 -static int iscsi_truncate(BlockDriverState *bs, int64_t offset, - PreallocMode prealloc, Error **errp) +static int coroutine_fn iscsi_co_truncate(BlockDriverState *bs, int64_t of= fset, + PreallocMode prealloc, Error **e= rrp) { IscsiLun *iscsilun =3D bs->opaque; Error *local_err =3D NULL; @@ -2431,7 +2431,7 @@ static BlockDriver bdrv_iscsi =3D { =20 .bdrv_getlength =3D iscsi_getlength, .bdrv_get_info =3D iscsi_get_info, - .bdrv_truncate =3D iscsi_truncate, + .bdrv_co_truncate =3D iscsi_co_truncate, .bdrv_refresh_limits =3D iscsi_refresh_limits, =20 .bdrv_co_block_status =3D iscsi_co_block_status, @@ -2468,7 +2468,7 @@ static BlockDriver bdrv_iser =3D { =20 .bdrv_getlength =3D iscsi_getlength, .bdrv_get_info =3D iscsi_get_info, - .bdrv_truncate =3D iscsi_truncate, + .bdrv_co_truncate =3D iscsi_co_truncate, .bdrv_refresh_limits =3D iscsi_refresh_limits, =20 .bdrv_co_block_status =3D iscsi_co_block_status, diff --git a/block/nfs.c b/block/nfs.c index 743ca0450e..eab1a2c408 100644 --- a/block/nfs.c +++ b/block/nfs.c @@ -743,8 +743,9 @@ static int64_t nfs_get_allocated_file_size(BlockDriverS= tate *bs) return (task.ret < 0 ? task.ret : st.st_blocks * 512); } =20 -static int nfs_file_truncate(BlockDriverState *bs, int64_t offset, - PreallocMode prealloc, Error **errp) +static int coroutine_fn +nfs_file_co_truncate(BlockDriverState *bs, int64_t offset, + PreallocMode prealloc, Error **errp) { NFSClient *client =3D bs->opaque; int ret; @@ -873,7 +874,7 @@ static BlockDriver bdrv_nfs =3D { =20 .bdrv_has_zero_init =3D nfs_has_zero_init, .bdrv_get_allocated_file_size =3D nfs_get_allocated_file_size, - .bdrv_truncate =3D nfs_file_truncate, + .bdrv_co_truncate =3D nfs_file_co_truncate, =20 .bdrv_file_open =3D nfs_file_open, .bdrv_close =3D nfs_file_close, diff --git a/block/qcow2.c b/block/qcow2.c index 6b2e1e1058..cd1836bc5b 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -2543,15 +2543,12 @@ static void coroutine_fn preallocate_co(void *opaqu= e) BlockDriverState *bs =3D params->bs; uint64_t offset =3D params->offset; uint64_t new_length =3D params->new_length; - BDRVQcow2State *s =3D bs->opaque; uint64_t bytes; uint64_t host_offset =3D 0; unsigned int cur_bytes; int ret; QCowL2Meta *meta; =20 - qemu_co_mutex_lock(&s->lock); - assert(offset <=3D new_length); bytes =3D new_length - offset; =20 @@ -2604,7 +2601,6 @@ static void coroutine_fn preallocate_co(void *opaque) ret =3D 0; =20 done: - qemu_co_mutex_unlock(&s->lock); params->ret =3D ret; } =20 @@ -3041,7 +3037,11 @@ qcow2_co_create(BlockdevCreateOptions *create_option= s, Error **errp) =20 /* And if we're supposed to preallocate metadata, do that now */ if (qcow2_opts->preallocation !=3D PREALLOC_MODE_OFF) { + BDRVQcow2State *s =3D blk_bs(blk)->opaque; + qemu_co_mutex_lock(&s->lock); ret =3D preallocate(blk_bs(blk), 0, qcow2_opts->size); + qemu_co_mutex_unlock(&s->lock); + if (ret < 0) { error_setg_errno(errp, -ret, "Could not preallocate metadata"); goto out; @@ -3437,8 +3437,8 @@ fail: return ret; } =20 -static int qcow2_truncate(BlockDriverState *bs, int64_t offset, - PreallocMode prealloc, Error **errp) +static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t of= fset, + PreallocMode prealloc, Error **e= rrp) { BDRVQcow2State *s =3D bs->opaque; uint64_t old_length; @@ -3458,17 +3458,21 @@ static int qcow2_truncate(BlockDriverState *bs, int= 64_t offset, return -EINVAL; } =20 + qemu_co_mutex_lock(&s->lock); + /* cannot proceed if image has snapshots */ if (s->nb_snapshots) { error_setg(errp, "Can't resize an image which has snapshots"); - return -ENOTSUP; + ret =3D -ENOTSUP; + goto fail; } =20 /* cannot proceed if image has bitmaps */ if (s->nb_bitmaps) { /* TODO: resize bitmaps in the image */ error_setg(errp, "Can't resize an image which has bitmaps"); - return -ENOTSUP; + ret =3D -ENOTSUP; + goto fail; } =20 old_length =3D bs->total_sectors * 512; @@ -3479,7 +3483,8 @@ static int qcow2_truncate(BlockDriverState *bs, int64= _t offset, if (prealloc !=3D PREALLOC_MODE_OFF) { error_setg(errp, "Preallocation can't be used for shrinking an image= "); - return -EINVAL; + ret =3D -EINVAL; + goto fail; } =20 ret =3D qcow2_cluster_discard(bs, ROUND_UP(offset, s->cluster_size= ), @@ -3488,40 +3493,42 @@ static int qcow2_truncate(BlockDriverState *bs, int= 64_t offset, QCOW2_DISCARD_ALWAYS, true); if (ret < 0) { error_setg_errno(errp, -ret, "Failed to discard cropped cluste= rs"); - return ret; + goto fail; } =20 ret =3D qcow2_shrink_l1_table(bs, new_l1_size); if (ret < 0) { error_setg_errno(errp, -ret, "Failed to reduce the number of L2 tables"); - return ret; + goto fail; } =20 ret =3D qcow2_shrink_reftable(bs); if (ret < 0) { error_setg_errno(errp, -ret, "Failed to discard unused refblocks"); - return ret; + goto fail; } =20 old_file_size =3D bdrv_getlength(bs->file->bs); if (old_file_size < 0) { error_setg_errno(errp, -old_file_size, "Failed to inquire current file length"); - return old_file_size; + ret =3D old_file_size; + goto fail; } last_cluster =3D qcow2_get_last_cluster(bs, old_file_size); if (last_cluster < 0) { error_setg_errno(errp, -last_cluster, "Failed to find the last cluster"); - return last_cluster; + ret =3D last_cluster; + goto fail; } if ((last_cluster + 1) * s->cluster_size < old_file_size) { Error *local_err =3D NULL; =20 - bdrv_truncate(bs->file, (last_cluster + 1) * s->cluster_size, - PREALLOC_MODE_OFF, &local_err); + bdrv_co_truncate(bs->file, (last_cluster + 1) * s->cluster_siz= e, + PREALLOC_MODE_OFF, &local_err); if (local_err) { warn_reportf_err(local_err, "Failed to truncate the tail of the image= : "); @@ -3531,7 +3538,7 @@ static int qcow2_truncate(BlockDriverState *bs, int64= _t offset, ret =3D qcow2_grow_l1_table(bs, new_l1_size, true); if (ret < 0) { error_setg_errno(errp, -ret, "Failed to grow the L1 table"); - return ret; + goto fail; } } =20 @@ -3543,7 +3550,7 @@ static int qcow2_truncate(BlockDriverState *bs, int64= _t offset, ret =3D preallocate(bs, old_length, offset); if (ret < 0) { error_setg_errno(errp, -ret, "Preallocation failed"); - return ret; + goto fail; } break; =20 @@ -3559,7 +3566,8 @@ static int qcow2_truncate(BlockDriverState *bs, int64= _t offset, if (old_file_size < 0) { error_setg_errno(errp, -old_file_size, "Failed to inquire current file length"); - return old_file_size; + ret =3D old_file_size; + goto fail; } old_file_size =3D ROUND_UP(old_file_size, s->cluster_size); =20 @@ -3589,7 +3597,8 @@ static int qcow2_truncate(BlockDriverState *bs, int64= _t offset, if (allocation_start < 0) { error_setg_errno(errp, -allocation_start, "Failed to resize refcount structures"); - return allocation_start; + ret =3D allocation_start; + goto fail; } =20 clusters_allocated =3D qcow2_alloc_clusters_at(bs, allocation_star= t, @@ -3597,7 +3606,8 @@ static int qcow2_truncate(BlockDriverState *bs, int64= _t offset, if (clusters_allocated < 0) { error_setg_errno(errp, -clusters_allocated, "Failed to allocate data clusters"); - return clusters_allocated; + ret =3D clusters_allocated; + goto fail; } =20 assert(clusters_allocated =3D=3D nb_new_data_clusters); @@ -3605,13 +3615,13 @@ static int qcow2_truncate(BlockDriverState *bs, int= 64_t offset, /* Allocate the data area */ new_file_size =3D allocation_start + nb_new_data_clusters * s->cluster_size; - ret =3D bdrv_truncate(bs->file, new_file_size, prealloc, errp); + ret =3D bdrv_co_truncate(bs->file, new_file_size, prealloc, errp); if (ret < 0) { error_prepend(errp, "Failed to resize underlying file: "); qcow2_free_clusters(bs, allocation_start, nb_new_data_clusters * s->cluster_size, QCOW2_DISCARD_OTHER); - return ret; + goto fail; } =20 /* Create the necessary L2 entries */ @@ -3634,7 +3644,7 @@ static int qcow2_truncate(BlockDriverState *bs, int64= _t offset, qcow2_free_clusters(bs, host_offset, nb_new_data_clusters * s->cluster_size, QCOW2_DISCARD_OTHER); - return ret; + goto fail; } =20 guest_offset +=3D nb_clusters * s->cluster_size; @@ -3650,11 +3660,11 @@ static int qcow2_truncate(BlockDriverState *bs, int= 64_t offset, =20 if (prealloc !=3D PREALLOC_MODE_OFF) { /* Flush metadata before actually changing the image size */ - ret =3D bdrv_flush(bs); + ret =3D qcow2_write_caches(bs); if (ret < 0) { error_setg_errno(errp, -ret, "Failed to flush the preallocated area to dis= k"); - return ret; + goto fail; } } =20 @@ -3664,11 +3674,14 @@ static int qcow2_truncate(BlockDriverState *bs, int= 64_t offset, &offset, sizeof(uint64_t)); if (ret < 0) { error_setg_errno(errp, -ret, "Failed to update the image size"); - return ret; + goto fail; } =20 s->l1_vm_state_index =3D new_l1_size; - return 0; + ret =3D 0; +fail: + qemu_co_mutex_unlock(&s->lock); + return ret; } =20 /* XXX: put compressed sectors first, then all the cluster aligned @@ -3692,7 +3705,7 @@ qcow2_co_pwritev_compressed(BlockDriverState *bs, uin= t64_t offset, if (cluster_offset < 0) { return cluster_offset; } - return bdrv_truncate(bs->file, cluster_offset, PREALLOC_MODE_OFF, = NULL); + return bdrv_co_truncate(bs->file, cluster_offset, PREALLOC_MODE_OF= F, NULL); } =20 if (offset_into_cluster(s, offset)) { @@ -4696,7 +4709,7 @@ BlockDriver bdrv_qcow2 =3D { .bdrv_co_pdiscard =3D qcow2_co_pdiscard, .bdrv_co_copy_range_from =3D qcow2_co_copy_range_from, .bdrv_co_copy_range_to =3D qcow2_co_copy_range_to, - .bdrv_truncate =3D qcow2_truncate, + .bdrv_co_truncate =3D qcow2_co_truncate, .bdrv_co_pwritev_compressed =3D qcow2_co_pwritev_compressed, .bdrv_make_empty =3D qcow2_make_empty, =20 diff --git a/block/qed.c b/block/qed.c index 2363814538..689ea9d4d5 100644 --- a/block/qed.c +++ b/block/qed.c @@ -1467,8 +1467,10 @@ static int coroutine_fn bdrv_qed_co_pwrite_zeroes(Bl= ockDriverState *bs, QED_AIOCB_WRITE | QED_AIOCB_ZERO); } =20 -static int bdrv_qed_truncate(BlockDriverState *bs, int64_t offset, - PreallocMode prealloc, Error **errp) +static int coroutine_fn bdrv_qed_co_truncate(BlockDriverState *bs, + int64_t offset, + PreallocMode prealloc, + Error **errp) { BDRVQEDState *s =3D bs->opaque; uint64_t old_image_size; @@ -1678,7 +1680,7 @@ static BlockDriver bdrv_qed =3D { .bdrv_co_readv =3D bdrv_qed_co_readv, .bdrv_co_writev =3D bdrv_qed_co_writev, .bdrv_co_pwrite_zeroes =3D bdrv_qed_co_pwrite_zeroes, - .bdrv_truncate =3D bdrv_qed_truncate, + .bdrv_co_truncate =3D bdrv_qed_co_truncate, .bdrv_getlength =3D bdrv_qed_getlength, .bdrv_get_info =3D bdrv_qed_get_info, .bdrv_refresh_limits =3D bdrv_qed_refresh_limits, diff --git a/block/raw-format.c b/block/raw-format.c index f2e468df6f..b78da564d4 100644 --- a/block/raw-format.c +++ b/block/raw-format.c @@ -366,8 +366,8 @@ static void raw_refresh_limits(BlockDriverState *bs, Er= ror **errp) } } =20 -static int raw_truncate(BlockDriverState *bs, int64_t offset, - PreallocMode prealloc, Error **errp) +static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offs= et, + PreallocMode prealloc, Error **err= p) { BDRVRawState *s =3D bs->opaque; =20 @@ -383,7 +383,7 @@ static int raw_truncate(BlockDriverState *bs, int64_t o= ffset, =20 s->size =3D offset; offset +=3D s->offset; - return bdrv_truncate(bs->file, offset, prealloc, errp); + return bdrv_co_truncate(bs->file, offset, prealloc, errp); } =20 static void raw_eject(BlockDriverState *bs, bool eject_flag) @@ -545,7 +545,7 @@ BlockDriver bdrv_raw =3D { .bdrv_co_block_status =3D &raw_co_block_status, .bdrv_co_copy_range_from =3D &raw_co_copy_range_from, .bdrv_co_copy_range_to =3D &raw_co_copy_range_to, - .bdrv_truncate =3D &raw_truncate, + .bdrv_co_truncate =3D &raw_co_truncate, .bdrv_getlength =3D &raw_getlength, .has_variable_length =3D true, .bdrv_measure =3D &raw_measure, diff --git a/block/rbd.c b/block/rbd.c index f2c6965418..ca8e5bbace 100644 --- a/block/rbd.c +++ b/block/rbd.c @@ -990,8 +990,10 @@ static int64_t qemu_rbd_getlength(BlockDriverState *bs) return info.size; } =20 -static int qemu_rbd_truncate(BlockDriverState *bs, int64_t offset, - PreallocMode prealloc, Error **errp) +static int coroutine_fn qemu_rbd_co_truncate(BlockDriverState *bs, + int64_t offset, + PreallocMode prealloc, + Error **errp) { BDRVRBDState *s =3D bs->opaque; int r; @@ -1184,7 +1186,7 @@ static BlockDriver bdrv_rbd =3D { .bdrv_get_info =3D qemu_rbd_getinfo, .create_opts =3D &qemu_rbd_create_opts, .bdrv_getlength =3D qemu_rbd_getlength, - .bdrv_truncate =3D qemu_rbd_truncate, + .bdrv_co_truncate =3D qemu_rbd_co_truncate, .protocol_name =3D "rbd", =20 .bdrv_aio_preadv =3D qemu_rbd_aio_preadv, diff --git a/block/sheepdog.c b/block/sheepdog.c index 665b1763eb..b229a664d9 100644 --- a/block/sheepdog.c +++ b/block/sheepdog.c @@ -2292,8 +2292,8 @@ static int64_t sd_getlength(BlockDriverState *bs) return s->inode.vdi_size; } =20 -static int sd_truncate(BlockDriverState *bs, int64_t offset, - PreallocMode prealloc, Error **errp) +static int coroutine_fn sd_co_truncate(BlockDriverState *bs, int64_t offse= t, + PreallocMode prealloc, Error **errp) { BDRVSheepdogState *s =3D bs->opaque; int ret, fd; @@ -2609,7 +2609,7 @@ static coroutine_fn int sd_co_writev(BlockDriverState= *bs, int64_t sector_num, =20 assert(!flags); if (offset > s->inode.vdi_size) { - ret =3D sd_truncate(bs, offset, PREALLOC_MODE_OFF, NULL); + ret =3D sd_co_truncate(bs, offset, PREALLOC_MODE_OFF, NULL); if (ret < 0) { return ret; } @@ -3231,7 +3231,7 @@ static BlockDriver bdrv_sheepdog =3D { .bdrv_has_zero_init =3D bdrv_has_zero_init_1, .bdrv_getlength =3D sd_getlength, .bdrv_get_allocated_file_size =3D sd_get_allocated_file_size, - .bdrv_truncate =3D sd_truncate, + .bdrv_co_truncate =3D sd_co_truncate, =20 .bdrv_co_readv =3D sd_co_readv, .bdrv_co_writev =3D sd_co_writev, @@ -3268,7 +3268,7 @@ static BlockDriver bdrv_sheepdog_tcp =3D { .bdrv_has_zero_init =3D bdrv_has_zero_init_1, .bdrv_getlength =3D sd_getlength, .bdrv_get_allocated_file_size =3D sd_get_allocated_file_size, - .bdrv_truncate =3D sd_truncate, + .bdrv_co_truncate =3D sd_co_truncate, =20 .bdrv_co_readv =3D sd_co_readv, .bdrv_co_writev =3D sd_co_writev, @@ -3305,7 +3305,7 @@ static BlockDriver bdrv_sheepdog_unix =3D { .bdrv_has_zero_init =3D bdrv_has_zero_init_1, .bdrv_getlength =3D sd_getlength, .bdrv_get_allocated_file_size =3D sd_get_allocated_file_size, - .bdrv_truncate =3D sd_truncate, + .bdrv_co_truncate =3D sd_co_truncate, =20 .bdrv_co_readv =3D sd_co_readv, .bdrv_co_writev =3D sd_co_writev, diff --git a/block/ssh.c b/block/ssh.c index da7bbf73e2..7fbc27abdf 100644 --- a/block/ssh.c +++ b/block/ssh.c @@ -1243,8 +1243,8 @@ static int64_t ssh_getlength(BlockDriverState *bs) return length; } =20 -static int ssh_truncate(BlockDriverState *bs, int64_t offset, - PreallocMode prealloc, Error **errp) +static int coroutine_fn ssh_co_truncate(BlockDriverState *bs, int64_t offs= et, + PreallocMode prealloc, Error **err= p) { BDRVSSHState *s =3D bs->opaque; =20 @@ -1279,7 +1279,7 @@ static BlockDriver bdrv_ssh =3D { .bdrv_co_readv =3D ssh_co_readv, .bdrv_co_writev =3D ssh_co_writev, .bdrv_getlength =3D ssh_getlength, - .bdrv_truncate =3D ssh_truncate, + .bdrv_co_truncate =3D ssh_co_truncate, .bdrv_co_flush_to_disk =3D ssh_co_flush, .create_opts =3D &ssh_create_opts, }; --=20 2.13.6 From nobody Fri May 17 18:58:11 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1530023241239108.16011184987076; Tue, 26 Jun 2018 07:27:21 -0700 (PDT) Received: from localhost ([::1]:53044 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fXowC-0003XH-Ez for importer@patchew.org; Tue, 26 Jun 2018 10:27:20 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:42884) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fXotk-0001rN-43 for qemu-devel@nongnu.org; Tue, 26 Jun 2018 10:24:50 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fXoti-000378-Vb for qemu-devel@nongnu.org; Tue, 26 Jun 2018 10:24:48 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:54380 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fXotg-0002uY-2D; Tue, 26 Jun 2018 10:24:44 -0400 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.rdu2.redhat.com [10.11.54.3]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id A451A406F8A3; Tue, 26 Jun 2018 14:24:43 +0000 (UTC) Received: from dhcp-200-186.str.redhat.com (dhcp-200-186.str.redhat.com [10.33.200.186]) by smtp.corp.redhat.com (Postfix) with ESMTP id BD2441117634; Tue, 26 Jun 2018 14:24:42 +0000 (UTC) From: Kevin Wolf To: qemu-block@nongnu.org Date: Tue, 26 Jun 2018 16:24:31 +0200 Message-Id: <20180626142434.22090-4-kwolf@redhat.com> In-Reply-To: <20180626142434.22090-1-kwolf@redhat.com> References: <20180626142434.22090-1-kwolf@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.3 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.7]); Tue, 26 Jun 2018 14:24:43 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.7]); Tue, 26 Jun 2018 14:24:43 +0000 (UTC) for IP:'10.11.54.3' DOMAIN:'int-mx03.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'kwolf@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PATCH v2 3/6] qcow2: Remove coroutine trampoline for preallocate_co() X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kwolf@redhat.com, qemu-devel@nongnu.org, stefanha@redhat.com, mreitz@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" All callers are coroutine_fns now, so we can just directly call preallocate_co(). Signed-off-by: Kevin Wolf Reviewed-by: Stefan Hajnoczi --- block/qcow2.c | 51 ++++++++------------------------------------------- 1 file changed, 8 insertions(+), 43 deletions(-) diff --git a/block/qcow2.c b/block/qcow2.c index cd1836bc5b..3062e34f5e 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -2521,15 +2521,6 @@ static int qcow2_set_up_encryption(BlockDriverState = *bs, return ret; } =20 - -typedef struct PreallocCo { - BlockDriverState *bs; - uint64_t offset; - uint64_t new_length; - - int ret; -} PreallocCo; - /** * Preallocates metadata structures for data clusters between @offset (in = the * guest disk) and @new_length (which is thus generally the new guest disk @@ -2537,12 +2528,9 @@ typedef struct PreallocCo { * * Returns: 0 on success, -errno on failure. */ -static void coroutine_fn preallocate_co(void *opaque) +static int coroutine_fn preallocate_co(BlockDriverState *bs, uint64_t offs= et, + uint64_t new_length) { - PreallocCo *params =3D opaque; - BlockDriverState *bs =3D params->bs; - uint64_t offset =3D params->offset; - uint64_t new_length =3D params->new_length; uint64_t bytes; uint64_t host_offset =3D 0; unsigned int cur_bytes; @@ -2557,7 +2545,7 @@ static void coroutine_fn preallocate_co(void *opaque) ret =3D qcow2_alloc_cluster_offset(bs, offset, &cur_bytes, &host_offset, &meta); if (ret < 0) { - goto done; + return ret; } =20 while (meta) { @@ -2567,7 +2555,7 @@ static void coroutine_fn preallocate_co(void *opaque) if (ret < 0) { qcow2_free_any_clusters(bs, meta->alloc_offset, meta->nb_clusters, QCOW2_DISCARD_N= EVER); - goto done; + return ret; } =20 /* There are no dependent requests, but we need to remove our @@ -2594,34 +2582,11 @@ static void coroutine_fn preallocate_co(void *opaqu= e) ret =3D bdrv_pwrite(bs->file, (host_offset + cur_bytes) - 1, &data, 1); if (ret < 0) { - goto done; + return ret; } } =20 - ret =3D 0; - -done: - params->ret =3D ret; -} - -static int preallocate(BlockDriverState *bs, - uint64_t offset, uint64_t new_length) -{ - PreallocCo params =3D { - .bs =3D bs, - .offset =3D offset, - .new_length =3D new_length, - .ret =3D -EINPROGRESS, - }; - - if (qemu_in_coroutine()) { - preallocate_co(¶ms); - } else { - Coroutine *co =3D qemu_coroutine_create(preallocate_co, ¶ms); - bdrv_coroutine_enter(bs, co); - BDRV_POLL_WHILE(bs, params.ret =3D=3D -EINPROGRESS); - } - return params.ret; + return 0; } =20 /* qcow2_refcount_metadata_size: @@ -3039,7 +3004,7 @@ qcow2_co_create(BlockdevCreateOptions *create_options= , Error **errp) if (qcow2_opts->preallocation !=3D PREALLOC_MODE_OFF) { BDRVQcow2State *s =3D blk_bs(blk)->opaque; qemu_co_mutex_lock(&s->lock); - ret =3D preallocate(blk_bs(blk), 0, qcow2_opts->size); + ret =3D preallocate_co(blk_bs(blk), 0, qcow2_opts->size); qemu_co_mutex_unlock(&s->lock); =20 if (ret < 0) { @@ -3547,7 +3512,7 @@ static int coroutine_fn qcow2_co_truncate(BlockDriver= State *bs, int64_t offset, break; =20 case PREALLOC_MODE_METADATA: - ret =3D preallocate(bs, old_length, offset); + ret =3D preallocate_co(bs, old_length, offset); if (ret < 0) { error_setg_errno(errp, -ret, "Preallocation failed"); goto fail; --=20 2.13.6 From nobody Fri May 17 18:58:11 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1530023483006842.6411921993626; Tue, 26 Jun 2018 07:31:23 -0700 (PDT) Received: from localhost ([::1]:53070 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fXp06-0006l2-6T for importer@patchew.org; Tue, 26 Jun 2018 10:31:22 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:42951) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fXotp-0001vl-Cx for qemu-devel@nongnu.org; Tue, 26 Jun 2018 10:24:55 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fXotm-0003QB-Hr for qemu-devel@nongnu.org; Tue, 26 Jun 2018 10:24:53 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:54382 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fXoth-0002z1-62; Tue, 26 Jun 2018 10:24:45 -0400 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.rdu2.redhat.com [10.11.54.3]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id C2BB5406F8A3; Tue, 26 Jun 2018 14:24:44 +0000 (UTC) Received: from dhcp-200-186.str.redhat.com (dhcp-200-186.str.redhat.com [10.33.200.186]) by smtp.corp.redhat.com (Postfix) with ESMTP id DB87F1117634; Tue, 26 Jun 2018 14:24:43 +0000 (UTC) From: Kevin Wolf To: qemu-block@nongnu.org Date: Tue, 26 Jun 2018 16:24:32 +0200 Message-Id: <20180626142434.22090-5-kwolf@redhat.com> In-Reply-To: <20180626142434.22090-1-kwolf@redhat.com> References: <20180626142434.22090-1-kwolf@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.3 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.7]); Tue, 26 Jun 2018 14:24:44 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.7]); Tue, 26 Jun 2018 14:24:44 +0000 (UTC) for IP:'10.11.54.3' DOMAIN:'int-mx03.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'kwolf@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PATCH v2 4/6] block: Move bdrv_truncate() implementation to io.c X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kwolf@redhat.com, qemu-devel@nongnu.org, stefanha@redhat.com, mreitz@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" This moves the bdrv_truncate() implementation from block.c to block/io.c so it can have access to the tracked requests infrastructure. This involves making refresh_total_sectors() public (in block_int.h). Signed-off-by: Kevin Wolf Reviewed-by: Stefan Hajnoczi --- include/block/block_int.h | 2 + block.c | 111 +-----------------------------------------= ---- block/io.c | 109 ++++++++++++++++++++++++++++++++++++++++++= +++ 3 files changed, 112 insertions(+), 110 deletions(-) diff --git a/include/block/block_int.h b/include/block/block_int.h index c653ee663a..740166a996 100644 --- a/include/block/block_int.h +++ b/include/block/block_int.h @@ -1157,4 +1157,6 @@ int coroutine_fn bdrv_co_copy_range_to(BdrvChild *src= , uint64_t src_offset, BdrvChild *dst, uint64_t dst_offset, uint64_t bytes, BdrvRequestFlags fl= ags); =20 +int refresh_total_sectors(BlockDriverState *bs, int64_t hint); + #endif /* BLOCK_INT_H */ diff --git a/block.c b/block.c index f761bc85d5..70a46fdd84 100644 --- a/block.c +++ b/block.c @@ -725,7 +725,7 @@ static int find_image_format(BlockBackend *file, const = char *filename, * Set the current 'total_sectors' value * Return 0 on success, -errno on error. */ -static int refresh_total_sectors(BlockDriverState *bs, int64_t hint) +int refresh_total_sectors(BlockDriverState *bs, int64_t hint) { BlockDriver *drv =3D bs->drv; =20 @@ -2226,16 +2226,6 @@ static void bdrv_parent_cb_change_media(BlockDriverS= tate *bs, bool load) } } =20 -static void bdrv_parent_cb_resize(BlockDriverState *bs) -{ - BdrvChild *c; - QLIST_FOREACH(c, &bs->parents, next_parent) { - if (c->role->resize) { - c->role->resize(c); - } - } -} - /* * Sets the backing file link of a BDS. A new reference is created; callers * which don't need their own reference any more must call bdrv_unref(). @@ -3786,105 +3776,6 @@ exit: } =20 /** - * Truncate file to 'offset' bytes (needed only for file protocols) - */ -int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, - PreallocMode prealloc, Error **errp) -{ - BlockDriverState *bs =3D child->bs; - BlockDriver *drv =3D bs->drv; - int ret; - - assert(child->perm & BLK_PERM_RESIZE); - - /* if bs->drv =3D=3D NULL, bs is closed, so there's nothing to do here= */ - if (!drv) { - error_setg(errp, "No medium inserted"); - return -ENOMEDIUM; - } - if (offset < 0) { - error_setg(errp, "Image size cannot be negative"); - return -EINVAL; - } - - bdrv_inc_in_flight(bs); - - if (!drv->bdrv_co_truncate) { - if (bs->file && drv->is_filter) { - ret =3D bdrv_co_truncate(bs->file, offset, prealloc, errp); - goto out; - } - error_setg(errp, "Image format driver does not support resize"); - ret =3D -ENOTSUP; - goto out; - } - if (bs->read_only) { - error_setg(errp, "Image is read-only"); - ret =3D -EACCES; - goto out; - } - - assert(!(bs->open_flags & BDRV_O_INACTIVE)); - - ret =3D drv->bdrv_co_truncate(bs, offset, prealloc, errp); - if (ret < 0) { - goto out; - } - ret =3D refresh_total_sectors(bs, offset >> BDRV_SECTOR_BITS); - if (ret < 0) { - error_setg_errno(errp, -ret, "Could not refresh total sector count= "); - } else { - offset =3D bs->total_sectors * BDRV_SECTOR_SIZE; - } - bdrv_dirty_bitmap_truncate(bs, offset); - bdrv_parent_cb_resize(bs); - atomic_inc(&bs->write_gen); - -out: - bdrv_dec_in_flight(bs); - return ret; -} - -typedef struct TruncateCo { - BdrvChild *child; - int64_t offset; - PreallocMode prealloc; - Error **errp; - int ret; -} TruncateCo; - -static void coroutine_fn bdrv_truncate_co_entry(void *opaque) -{ - TruncateCo *tco =3D opaque; - tco->ret =3D bdrv_co_truncate(tco->child, tco->offset, tco->prealloc, - tco->errp); -} - -int bdrv_truncate(BdrvChild *child, int64_t offset, PreallocMode prealloc, - Error **errp) -{ - Coroutine *co; - TruncateCo tco =3D { - .child =3D child, - .offset =3D offset, - .prealloc =3D prealloc, - .errp =3D errp, - .ret =3D NOT_DONE, - }; - - if (qemu_in_coroutine()) { - /* Fast-path if already in coroutine context */ - bdrv_truncate_co_entry(&tco); - } else { - co =3D qemu_coroutine_create(bdrv_truncate_co_entry, &tco); - qemu_coroutine_enter(co); - BDRV_POLL_WHILE(child->bs, tco.ret =3D=3D NOT_DONE); - } - - return tco.ret; -} - -/** * Length of a allocated file in bytes. Sparse files are counted by actual * allocated space. Return < 0 if error or unknown. */ diff --git a/block/io.c b/block/io.c index ef4fedd364..7e87a42b8e 100644 --- a/block/io.c +++ b/block/io.c @@ -3020,3 +3020,112 @@ int coroutine_fn bdrv_co_copy_range(BdrvChild *src,= uint64_t src_offset, bdrv_dec_in_flight(dst_bs); return ret; } + +static void bdrv_parent_cb_resize(BlockDriverState *bs) +{ + BdrvChild *c; + QLIST_FOREACH(c, &bs->parents, next_parent) { + if (c->role->resize) { + c->role->resize(c); + } + } +} + +/** + * Truncate file to 'offset' bytes (needed only for file protocols) + */ +int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, + PreallocMode prealloc, Error **errp) +{ + BlockDriverState *bs =3D child->bs; + BlockDriver *drv =3D bs->drv; + int ret; + + assert(child->perm & BLK_PERM_RESIZE); + + /* if bs->drv =3D=3D NULL, bs is closed, so there's nothing to do here= */ + if (!drv) { + error_setg(errp, "No medium inserted"); + return -ENOMEDIUM; + } + if (offset < 0) { + error_setg(errp, "Image size cannot be negative"); + return -EINVAL; + } + + bdrv_inc_in_flight(bs); + + if (!drv->bdrv_co_truncate) { + if (bs->file && drv->is_filter) { + ret =3D bdrv_co_truncate(bs->file, offset, prealloc, errp); + goto out; + } + error_setg(errp, "Image format driver does not support resize"); + ret =3D -ENOTSUP; + goto out; + } + if (bs->read_only) { + error_setg(errp, "Image is read-only"); + ret =3D -EACCES; + goto out; + } + + assert(!(bs->open_flags & BDRV_O_INACTIVE)); + + ret =3D drv->bdrv_co_truncate(bs, offset, prealloc, errp); + if (ret < 0) { + goto out; + } + ret =3D refresh_total_sectors(bs, offset >> BDRV_SECTOR_BITS); + if (ret < 0) { + error_setg_errno(errp, -ret, "Could not refresh total sector count= "); + } else { + offset =3D bs->total_sectors * BDRV_SECTOR_SIZE; + } + bdrv_dirty_bitmap_truncate(bs, offset); + bdrv_parent_cb_resize(bs); + atomic_inc(&bs->write_gen); + +out: + bdrv_dec_in_flight(bs); + return ret; +} + +typedef struct TruncateCo { + BdrvChild *child; + int64_t offset; + PreallocMode prealloc; + Error **errp; + int ret; +} TruncateCo; + +static void coroutine_fn bdrv_truncate_co_entry(void *opaque) +{ + TruncateCo *tco =3D opaque; + tco->ret =3D bdrv_co_truncate(tco->child, tco->offset, tco->prealloc, + tco->errp); +} + +int bdrv_truncate(BdrvChild *child, int64_t offset, PreallocMode prealloc, + Error **errp) +{ + Coroutine *co; + TruncateCo tco =3D { + .child =3D child, + .offset =3D offset, + .prealloc =3D prealloc, + .errp =3D errp, + .ret =3D NOT_DONE, + }; + + if (qemu_in_coroutine()) { + /* Fast-path if already in coroutine context */ + bdrv_truncate_co_entry(&tco); + } else { + co =3D qemu_coroutine_create(bdrv_truncate_co_entry, &tco); + qemu_coroutine_enter(co); + BDRV_POLL_WHILE(child->bs, tco.ret =3D=3D NOT_DONE); + } + + return tco.ret; +} --=20 2.13.6 From nobody Fri May 17 18:58:11 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1530023382611771.1696006386438; Tue, 26 Jun 2018 07:29:42 -0700 (PDT) Received: from localhost ([::1]:53057 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fXoyT-0005bE-PD for importer@patchew.org; Tue, 26 Jun 2018 10:29:41 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:42953) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fXotp-0001vm-Eb for qemu-devel@nongnu.org; Tue, 26 Jun 2018 10:24:54 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fXotm-0003Pq-GR for qemu-devel@nongnu.org; Tue, 26 Jun 2018 10:24:53 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:54384 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fXoti-00033I-8i; Tue, 26 Jun 2018 10:24:46 -0400 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.rdu2.redhat.com [10.11.54.3]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id E0D9A406F8A3; Tue, 26 Jun 2018 14:24:45 +0000 (UTC) Received: from dhcp-200-186.str.redhat.com (dhcp-200-186.str.redhat.com [10.33.200.186]) by smtp.corp.redhat.com (Postfix) with ESMTP id 0614E1117634; Tue, 26 Jun 2018 14:24:44 +0000 (UTC) From: Kevin Wolf To: qemu-block@nongnu.org Date: Tue, 26 Jun 2018 16:24:33 +0200 Message-Id: <20180626142434.22090-6-kwolf@redhat.com> In-Reply-To: <20180626142434.22090-1-kwolf@redhat.com> References: <20180626142434.22090-1-kwolf@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.3 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.7]); Tue, 26 Jun 2018 14:24:45 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.7]); Tue, 26 Jun 2018 14:24:45 +0000 (UTC) for IP:'10.11.54.3' DOMAIN:'int-mx03.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'kwolf@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PATCH v2 5/6] block: Use tracked request for truncate X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kwolf@redhat.com, qemu-devel@nongnu.org, stefanha@redhat.com, mreitz@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" When growing an image, block drivers (especially protocol drivers) may initialise the newly added area. I/O requests to the same area need to wait for this initialisation to be completed so that data writes don't get overwritten and reads don't read uninitialised data. To avoid overhead in the fast I/O path by adding new locking in the protocol drivers and to restrict the impact to requests that actually touch the new area, reuse the existing tracked request infrastructure in block/io.c and mark all discard requests as serialising. With this change, it is safe for protocol drivers to make .bdrv_co_truncate actually asynchronous. Signed-off-by: Kevin Wolf Reviewed-by: Stefan Hajnoczi --- include/block/block_int.h | 1 + block/io.c | 25 +++++++++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/include/block/block_int.h b/include/block/block_int.h index 740166a996..af71b414be 100644 --- a/include/block/block_int.h +++ b/include/block/block_int.h @@ -63,6 +63,7 @@ enum BdrvTrackedRequestType { BDRV_TRACKED_READ, BDRV_TRACKED_WRITE, BDRV_TRACKED_DISCARD, + BDRV_TRACKED_TRUNCATE, }; =20 typedef struct BdrvTrackedRequest { diff --git a/block/io.c b/block/io.c index 7e87a42b8e..01a3c4eac5 100644 --- a/block/io.c +++ b/block/io.c @@ -3039,6 +3039,8 @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, i= nt64_t offset, { BlockDriverState *bs =3D child->bs; BlockDriver *drv =3D bs->drv; + BdrvTrackedRequest req; + int64_t old_size, new_bytes; int ret; =20 assert(child->perm & BLK_PERM_RESIZE); @@ -3053,7 +3055,28 @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, = int64_t offset, return -EINVAL; } =20 + old_size =3D bdrv_getlength(bs); + if (old_size < 0) { + error_setg_errno(errp, -old_size, "Failed to get old image size"); + return old_size; + } + + if (offset > old_size) { + new_bytes =3D offset - old_size; + } else { + new_bytes =3D 0; + } + bdrv_inc_in_flight(bs); + tracked_request_begin(&req, bs, offset, new_bytes, BDRV_TRACKED_TRUNCA= TE); + + /* If we are growing the image and potentially using preallocation for= the + * new area, we need to make sure that no write requests are made to it + * concurrently or they might be overwritten by preallocation. */ + if (new_bytes) { + mark_request_serialising(&req, 1); + wait_serialising_requests(&req); + } =20 if (!drv->bdrv_co_truncate) { if (bs->file && drv->is_filter) { @@ -3087,7 +3110,9 @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, i= nt64_t offset, atomic_inc(&bs->write_gen); =20 out: + tracked_request_end(&req); bdrv_dec_in_flight(bs); + return ret; } =20 --=20 2.13.6 From nobody Fri May 17 18:58:11 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (208.118.235.17 [208.118.235.17]) by mx.zohomail.com with SMTPS id 1530023248309140.44699190729432; Tue, 26 Jun 2018 07:27:28 -0700 (PDT) Received: from localhost ([::1]:53043 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fXowB-0003VY-4e for importer@patchew.org; Tue, 26 Jun 2018 10:27:19 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:42981) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fXots-0001zW-1q for qemu-devel@nongnu.org; Tue, 26 Jun 2018 10:24:58 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fXotq-0003mX-1c for qemu-devel@nongnu.org; Tue, 26 Jun 2018 10:24:56 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:54000 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fXotj-000380-FM; Tue, 26 Jun 2018 10:24:47 -0400 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.rdu2.redhat.com [10.11.54.3]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 0AD5F87AC7; Tue, 26 Jun 2018 14:24:47 +0000 (UTC) Received: from dhcp-200-186.str.redhat.com (dhcp-200-186.str.redhat.com [10.33.200.186]) by smtp.corp.redhat.com (Postfix) with ESMTP id 2357C1117634; Tue, 26 Jun 2018 14:24:46 +0000 (UTC) From: Kevin Wolf To: qemu-block@nongnu.org Date: Tue, 26 Jun 2018 16:24:34 +0200 Message-Id: <20180626142434.22090-7-kwolf@redhat.com> In-Reply-To: <20180626142434.22090-1-kwolf@redhat.com> References: <20180626142434.22090-1-kwolf@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.3 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.1]); Tue, 26 Jun 2018 14:24:47 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.1]); Tue, 26 Jun 2018 14:24:47 +0000 (UTC) for IP:'10.11.54.3' DOMAIN:'int-mx03.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'kwolf@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PATCH v2 6/6] file-posix: Make .bdrv_co_truncate asynchronous X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kwolf@redhat.com, qemu-devel@nongnu.org, stefanha@redhat.com, mreitz@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" This moves the code to resize an image file to the thread pool to avoid blocking. Creating large images with preallocation with blockdev-create is now actually a background job instead of blocking the monitor (and most other things) until the preallocation has completed. Signed-off-by: Kevin Wolf Reviewed-by: Stefan Hajnoczi --- include/block/raw-aio.h | 4 +- block/file-posix.c | 265 +++++++++++++++++++++++++++-----------------= ---- 2 files changed, 153 insertions(+), 116 deletions(-) diff --git a/include/block/raw-aio.h b/include/block/raw-aio.h index 0e717fd475..e496ae31b2 100644 --- a/include/block/raw-aio.h +++ b/include/block/raw-aio.h @@ -26,6 +26,7 @@ #define QEMU_AIO_DISCARD 0x0010 #define QEMU_AIO_WRITE_ZEROES 0x0020 #define QEMU_AIO_COPY_RANGE 0x0040 +#define QEMU_AIO_TRUNCATE 0x0080 #define QEMU_AIO_TYPE_MASK \ (QEMU_AIO_READ | \ QEMU_AIO_WRITE | \ @@ -33,7 +34,8 @@ QEMU_AIO_FLUSH | \ QEMU_AIO_DISCARD | \ QEMU_AIO_WRITE_ZEROES | \ - QEMU_AIO_COPY_RANGE) + QEMU_AIO_COPY_RANGE | \ + QEMU_AIO_TRUNCATE) =20 /* AIO flags */ #define QEMU_AIO_MISALIGNED 0x1000 diff --git a/block/file-posix.c b/block/file-posix.c index 6223a8bccc..fa918f2bdb 100644 --- a/block/file-posix.c +++ b/block/file-posix.c @@ -188,8 +188,16 @@ typedef struct RawPosixAIOData { #define aio_ioctl_cmd aio_nbytes /* for QEMU_AIO_IOCTL */ off_t aio_offset; int aio_type; - int aio_fd2; - off_t aio_offset2; + union { + struct { + int aio_fd2; + off_t aio_offset2; + }; + struct { + PreallocMode prealloc; + Error **errp; + }; + }; } RawPosixAIOData; =20 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) @@ -1533,6 +1541,121 @@ static ssize_t handle_aiocb_discard(RawPosixAIOData= *aiocb) return ret; } =20 +static int handle_aiocb_truncate(RawPosixAIOData *aiocb) +{ + int result =3D 0; + int64_t current_length =3D 0; + char *buf =3D NULL; + struct stat st; + int fd =3D aiocb->aio_fildes; + int64_t offset =3D aiocb->aio_offset; + Error **errp =3D aiocb->errp; + + if (fstat(fd, &st) < 0) { + result =3D -errno; + error_setg_errno(errp, -result, "Could not stat file"); + return result; + } + + current_length =3D st.st_size; + if (current_length > offset && aiocb->prealloc !=3D PREALLOC_MODE_OFF)= { + error_setg(errp, "Cannot use preallocation for shrinking files"); + return -ENOTSUP; + } + + switch (aiocb->prealloc) { +#ifdef CONFIG_POSIX_FALLOCATE + case PREALLOC_MODE_FALLOC: + /* + * Truncating before posix_fallocate() makes it about twice slower= on + * file systems that do not support fallocate(), trying to check i= f a + * block is allocated before allocating it, so don't do that here. + */ + if (offset !=3D current_length) { + result =3D -posix_fallocate(fd, current_length, offset - curre= nt_length); + if (result !=3D 0) { + /* posix_fallocate() doesn't set errno. */ + error_setg_errno(errp, -result, + "Could not preallocate new data"); + } + } else { + result =3D 0; + } + goto out; +#endif + case PREALLOC_MODE_FULL: + { + int64_t num =3D 0, left =3D offset - current_length; + off_t seek_result; + + /* + * Knowing the final size from the beginning could allow the file + * system driver to do less allocations and possibly avoid + * fragmentation of the file. + */ + if (ftruncate(fd, offset) !=3D 0) { + result =3D -errno; + error_setg_errno(errp, -result, "Could not resize file"); + goto out; + } + + buf =3D g_malloc0(65536); + + seek_result =3D lseek(fd, current_length, SEEK_SET); + if (seek_result < 0) { + result =3D -errno; + error_setg_errno(errp, -result, + "Failed to seek to the old end of file"); + goto out; + } + + while (left > 0) { + num =3D MIN(left, 65536); + result =3D write(fd, buf, num); + if (result < 0) { + result =3D -errno; + error_setg_errno(errp, -result, + "Could not write zeros for preallocation"= ); + goto out; + } + left -=3D result; + } + if (result >=3D 0) { + result =3D fsync(fd); + if (result < 0) { + result =3D -errno; + error_setg_errno(errp, -result, + "Could not flush file to disk"); + goto out; + } + } + goto out; + } + case PREALLOC_MODE_OFF: + if (ftruncate(fd, offset) !=3D 0) { + result =3D -errno; + error_setg_errno(errp, -result, "Could not resize file"); + } + return result; + default: + result =3D -ENOTSUP; + error_setg(errp, "Unsupported preallocation mode: %s", + PreallocMode_str(aiocb->prealloc)); + return result; + } + +out: + if (result < 0) { + if (ftruncate(fd, current_length) < 0) { + error_report("Failed to restore old file length: %s", + strerror(errno)); + } + } + + g_free(buf); + return result; +} + static int aio_worker(void *arg) { RawPosixAIOData *aiocb =3D arg; @@ -1576,6 +1699,9 @@ static int aio_worker(void *arg) case QEMU_AIO_COPY_RANGE: ret =3D handle_aiocb_copy_range(aiocb); break; + case QEMU_AIO_TRUNCATE: + ret =3D handle_aiocb_truncate(aiocb); + break; default: fprintf(stderr, "invalid aio request (0x%x)\n", aiocb->aio_type); ret =3D -EINVAL; @@ -1743,117 +1869,25 @@ static void raw_close(BlockDriverState *bs) * * Returns: 0 on success, -errno on failure. */ -static int raw_regular_truncate(int fd, int64_t offset, PreallocMode preal= loc, - Error **errp) +static int coroutine_fn +raw_regular_truncate(BlockDriverState *bs, int fd, int64_t offset, + PreallocMode prealloc, Error **errp) { - int result =3D 0; - int64_t current_length =3D 0; - char *buf =3D NULL; - struct stat st; - - if (fstat(fd, &st) < 0) { - result =3D -errno; - error_setg_errno(errp, -result, "Could not stat file"); - return result; - } - - current_length =3D st.st_size; - if (current_length > offset && prealloc !=3D PREALLOC_MODE_OFF) { - error_setg(errp, "Cannot use preallocation for shrinking files"); - return -ENOTSUP; - } - - switch (prealloc) { -#ifdef CONFIG_POSIX_FALLOCATE - case PREALLOC_MODE_FALLOC: - /* - * Truncating before posix_fallocate() makes it about twice slower= on - * file systems that do not support fallocate(), trying to check i= f a - * block is allocated before allocating it, so don't do that here. - */ - if (offset !=3D current_length) { - result =3D -posix_fallocate(fd, current_length, offset - curre= nt_length); - if (result !=3D 0) { - /* posix_fallocate() doesn't set errno. */ - error_setg_errno(errp, -result, - "Could not preallocate new data"); - } - } else { - result =3D 0; - } - goto out; -#endif - case PREALLOC_MODE_FULL: - { - int64_t num =3D 0, left =3D offset - current_length; - off_t seek_result; - - /* - * Knowing the final size from the beginning could allow the file - * system driver to do less allocations and possibly avoid - * fragmentation of the file. - */ - if (ftruncate(fd, offset) !=3D 0) { - result =3D -errno; - error_setg_errno(errp, -result, "Could not resize file"); - goto out; - } - - buf =3D g_malloc0(65536); - - seek_result =3D lseek(fd, current_length, SEEK_SET); - if (seek_result < 0) { - result =3D -errno; - error_setg_errno(errp, -result, - "Failed to seek to the old end of file"); - goto out; - } - - while (left > 0) { - num =3D MIN(left, 65536); - result =3D write(fd, buf, num); - if (result < 0) { - result =3D -errno; - error_setg_errno(errp, -result, - "Could not write zeros for preallocation"= ); - goto out; - } - left -=3D result; - } - if (result >=3D 0) { - result =3D fsync(fd); - if (result < 0) { - result =3D -errno; - error_setg_errno(errp, -result, - "Could not flush file to disk"); - goto out; - } - } - goto out; - } - case PREALLOC_MODE_OFF: - if (ftruncate(fd, offset) !=3D 0) { - result =3D -errno; - error_setg_errno(errp, -result, "Could not resize file"); - } - return result; - default: - result =3D -ENOTSUP; - error_setg(errp, "Unsupported preallocation mode: %s", - PreallocMode_str(prealloc)); - return result; - } + RawPosixAIOData *acb =3D g_new(RawPosixAIOData, 1); + ThreadPool *pool; =20 -out: - if (result < 0) { - if (ftruncate(fd, current_length) < 0) { - error_report("Failed to restore old file length: %s", - strerror(errno)); - } - } + *acb =3D (RawPosixAIOData) { + .bs =3D bs, + .aio_fildes =3D fd, + .aio_type =3D QEMU_AIO_TRUNCATE, + .aio_offset =3D offset, + .prealloc =3D prealloc, + .errp =3D errp, + }; =20 - g_free(buf); - return result; + /* @bs can be NULL, bdrv_get_aio_context() returns the main context th= en */ + pool =3D aio_get_thread_pool(bdrv_get_aio_context(bs)); + return thread_pool_submit_co(pool, aio_worker, acb); } =20 static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offs= et, @@ -1870,7 +1904,7 @@ static int coroutine_fn raw_co_truncate(BlockDriverSt= ate *bs, int64_t offset, } =20 if (S_ISREG(st.st_mode)) { - return raw_regular_truncate(s->fd, offset, prealloc, errp); + return raw_regular_truncate(bs, s->fd, offset, prealloc, errp); } =20 if (prealloc !=3D PREALLOC_MODE_OFF) { @@ -2072,7 +2106,8 @@ static int64_t raw_get_allocated_file_size(BlockDrive= rState *bs) return (int64_t)st.st_blocks * 512; } =20 -static int raw_co_create(BlockdevCreateOptions *options, Error **errp) +static int coroutine_fn +raw_co_create(BlockdevCreateOptions *options, Error **errp) { BlockdevCreateOptionsFile *file_opts; int fd; @@ -2124,7 +2159,7 @@ static int raw_co_create(BlockdevCreateOptions *optio= ns, Error **errp) } =20 /* Clear the file by truncating it to 0 */ - result =3D raw_regular_truncate(fd, 0, PREALLOC_MODE_OFF, errp); + result =3D raw_regular_truncate(NULL, fd, 0, PREALLOC_MODE_OFF, errp); if (result < 0) { goto out_close; } @@ -2146,8 +2181,8 @@ static int raw_co_create(BlockdevCreateOptions *optio= ns, Error **errp) =20 /* Resize and potentially preallocate the file to the desired * final size */ - result =3D raw_regular_truncate(fd, file_opts->size, file_opts->preall= ocation, - errp); + result =3D raw_regular_truncate(NULL, fd, file_opts->size, + file_opts->preallocation, errp); if (result < 0) { goto out_close; } --=20 2.13.6