From nobody Tue Apr 30 01:48:53 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 1529601042596515.1592516894494; Thu, 21 Jun 2018 10:10:42 -0700 (PDT) Received: from localhost ([::1]:56763 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fW36W-0002yu-Mv for importer@patchew.org; Thu, 21 Jun 2018 13:10:40 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:49267) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fW33H-0000zB-1C for qemu-devel@nongnu.org; Thu, 21 Jun 2018 13:07:22 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fW33C-0006AJ-0M for qemu-devel@nongnu.org; Thu, 21 Jun 2018 13:07:19 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:45566 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 1fW336-000665-EP; Thu, 21 Jun 2018 13:07:08 -0400 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.rdu2.redhat.com [10.11.54.4]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 16D77C12A5; Thu, 21 Jun 2018 17:07:08 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-116-146.ams2.redhat.com [10.36.116.146]) by smtp.corp.redhat.com (Postfix) with ESMTP id 026B92026D6B; Thu, 21 Jun 2018 17:07:06 +0000 (UTC) From: Kevin Wolf To: qemu-block@nongnu.org Date: Thu, 21 Jun 2018 19:06:56 +0200 Message-Id: <20180621170657.27542-2-kwolf@redhat.com> In-Reply-To: <20180621170657.27542-1-kwolf@redhat.com> References: <20180621170657.27542-1-kwolf@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.4 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.1]); Thu, 21 Jun 2018 17:07:08 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.1]); Thu, 21 Jun 2018 17:07:08 +0000 (UTC) for IP:'10.11.54.4' DOMAIN:'int-mx04.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 1/2] 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, jcody@redhat.com, qemu-devel@nongnu.org, 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. Signed-off-by: Kevin Wolf --- include/block/block.h | 4 ++++ include/block/block_int.h | 4 ++-- block.c | 49 ++++++++++++++++++++++++++++++++++++++++++-= ---- 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 | 14 +++++++------- block/qed.c | 8 +++++--- block/raw-format.c | 8 ++++---- block/rbd.c | 8 +++++--- block/sheepdog.c | 12 ++++++------ block/ssh.c | 6 +++--- 16 files changed, 114 insertions(+), 63 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..39b7127945 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,9 +3807,9 @@ int bdrv_truncate(BdrvChild *child, int64_t offset, P= reallocMode prealloc, return -EINVAL; } =20 - if (!drv->bdrv_truncate) { + if (!drv->bdrv_co_truncate) { if (bs->file && drv->is_filter) { - return bdrv_truncate(bs->file, offset, prealloc, errp); + return bdrv_co_truncate(bs->file, offset, prealloc, errp); } error_setg(errp, "Image format driver does not support resize"); return -ENOTSUP; @@ -3821,7 +3821,7 @@ int bdrv_truncate(BdrvChild *child, int64_t offset, P= reallocMode prealloc, =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; } @@ -3837,6 +3837,45 @@ int bdrv_truncate(BdrvChild *child, int64_t offset, = PreallocMode prealloc, 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 82091c5f70..1b89ff129e 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 945132f692..b0b21889ac 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -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; @@ -3520,8 +3520,8 @@ static int qcow2_truncate(BlockDriverState *bs, int64= _t offset, 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= : "); @@ -3605,7 +3605,7 @@ static int qcow2_truncate(BlockDriverState *bs, int64= _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, @@ -3692,7 +3692,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)) { @@ -4697,7 +4697,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 Tue Apr 30 01:48:53 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 1529601054614167.36805713010938; Thu, 21 Jun 2018 10:10:54 -0700 (PDT) Received: from localhost ([::1]:56764 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fW36j-00037c-Ri for importer@patchew.org; Thu, 21 Jun 2018 13:10:53 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:49245) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fW33D-0000to-66 for qemu-devel@nongnu.org; Thu, 21 Jun 2018 13:07:18 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fW33B-00069S-KD for qemu-devel@nongnu.org; Thu, 21 Jun 2018 13:07:15 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:36506 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 1fW337-00066j-KB; Thu, 21 Jun 2018 13:07:09 -0400 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.rdu2.redhat.com [10.11.54.4]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 43B5520F30; Thu, 21 Jun 2018 17:07:09 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-116-146.ams2.redhat.com [10.36.116.146]) by smtp.corp.redhat.com (Postfix) with ESMTP id 527812026D6B; Thu, 21 Jun 2018 17:07:08 +0000 (UTC) From: Kevin Wolf To: qemu-block@nongnu.org Date: Thu, 21 Jun 2018 19:06:57 +0200 Message-Id: <20180621170657.27542-3-kwolf@redhat.com> In-Reply-To: <20180621170657.27542-1-kwolf@redhat.com> References: <20180621170657.27542-1-kwolf@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.4 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.2]); Thu, 21 Jun 2018 17:07:09 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.2]); Thu, 21 Jun 2018 17:07:09 +0000 (UTC) for IP:'10.11.54.4' DOMAIN:'int-mx04.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 2/2] 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, jcody@redhat.com, qemu-devel@nongnu.org, 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: Max Reitz --- 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