Blame SOURCES/kvm-block-Convert-.bdrv_truncate-callback-to-coroutine_f.patch

ae23c9
From 655e1605b0ec1e798482e36ccfcf43cfb983c26e Mon Sep 17 00:00:00 2001
ae23c9
From: Kevin Wolf <kwolf@redhat.com>
ae23c9
Date: Thu, 12 Jul 2018 14:42:54 +0200
ae23c9
Subject: [PATCH 209/268] block: Convert .bdrv_truncate callback to
ae23c9
 coroutine_fn
ae23c9
ae23c9
RH-Author: Kevin Wolf <kwolf@redhat.com>
ae23c9
Message-id: <20180712144258.17303-3-kwolf@redhat.com>
ae23c9
Patchwork-id: 81327
ae23c9
O-Subject: [RHV-7.6 qemu-kvm-rhev PATCH 2/6] block: Convert .bdrv_truncate callback to coroutine_fn
ae23c9
Bugzilla: 1595173
ae23c9
RH-Acked-by: Max Reitz <mreitz@redhat.com>
ae23c9
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
ae23c9
RH-Acked-by: John Snow <jsnow@redhat.com>
ae23c9
ae23c9
bdrv_truncate() is an operation that can block (even for a quite long
ae23c9
time, depending on the PreallocMode) in I/O paths that shouldn't block.
ae23c9
Convert it to a coroutine_fn so that we have the infrastructure for
ae23c9
drivers to make their .bdrv_co_truncate implementation asynchronous.
ae23c9
ae23c9
This change could potentially introduce new race conditions because
ae23c9
bdrv_truncate() isn't necessarily executed atomically any more. Whether
ae23c9
this is a problem needs to be evaluated for each block driver that
ae23c9
supports truncate:
ae23c9
ae23c9
* file-posix/win32, gluster, iscsi, nfs, rbd, ssh, sheepdog: The
ae23c9
  protocol drivers are trivially safe because they don't actually yield
ae23c9
  yet, so there is no change in behaviour.
ae23c9
ae23c9
* copy-on-read, crypto, raw-format: Essentially just filter drivers that
ae23c9
  pass the request to a child node, no problem.
ae23c9
ae23c9
* qcow2: The implementation modifies metadata, so it needs to hold
ae23c9
  s->lock to be safe with concurrent I/O requests. In order to avoid
ae23c9
  double locking, this requires pulling the locking out into
ae23c9
  preallocate_co() and using qcow2_write_caches() instead of
ae23c9
  bdrv_flush().
ae23c9
ae23c9
* qed: Does a single header update, this is fine without locking.
ae23c9
ae23c9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
ae23c9
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
ae23c9
(cherry picked from commit 061ca8a368165fae300748c17971824a089f521f)
ae23c9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
ae23c9
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
ae23c9
---
ae23c9
 block.c                   | 63 +++++++++++++++++++++++++++++++++++-----
ae23c9
 block/copy-on-read.c      |  8 ++---
ae23c9
 block/crypto.c            |  9 +++---
ae23c9
 block/file-posix.c        | 12 ++++----
ae23c9
 block/file-win32.c        |  6 ++--
ae23c9
 block/gluster.c           | 14 +++++----
ae23c9
 block/iscsi.c             |  8 ++---
ae23c9
 block/nfs.c               |  7 +++--
ae23c9
 block/qcow2.c             | 74 ++++++++++++++++++++++++++++-------------------
ae23c9
 block/qed.c               |  8 +++--
ae23c9
 block/raw-format.c        |  8 ++---
ae23c9
 block/rbd.c               |  8 +++--
ae23c9
 block/sheepdog.c          | 12 ++++----
ae23c9
 block/ssh.c               |  6 ++--
ae23c9
 include/block/block.h     |  4 +++
ae23c9
 include/block/block_int.h |  4 +--
ae23c9
 16 files changed, 162 insertions(+), 89 deletions(-)
ae23c9
ae23c9
diff --git a/block.c b/block.c
ae23c9
index 0516284..0af08ca 100644
ae23c9
--- a/block.c
ae23c9
+++ b/block.c
ae23c9
@@ -3738,8 +3738,8 @@ exit:
ae23c9
 /**
ae23c9
  * Truncate file to 'offset' bytes (needed only for file protocols)
ae23c9
  */
ae23c9
-int bdrv_truncate(BdrvChild *child, int64_t offset, PreallocMode prealloc,
ae23c9
-                  Error **errp)
ae23c9
+int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset,
ae23c9
+                                  PreallocMode prealloc, Error **errp)
ae23c9
 {
ae23c9
     BlockDriverState *bs = child->bs;
ae23c9
     BlockDriver *drv = bs->drv;
ae23c9
@@ -3757,23 +3757,28 @@ int bdrv_truncate(BdrvChild *child, int64_t offset, PreallocMode prealloc,
ae23c9
         return -EINVAL;
ae23c9
     }
ae23c9
 
ae23c9
-    if (!drv->bdrv_truncate) {
ae23c9
+    bdrv_inc_in_flight(bs);
ae23c9
+
ae23c9
+    if (!drv->bdrv_co_truncate) {
ae23c9
         if (bs->file && drv->is_filter) {
ae23c9
-            return bdrv_truncate(bs->file, offset, prealloc, errp);
ae23c9
+            ret = bdrv_co_truncate(bs->file, offset, prealloc, errp);
ae23c9
+            goto out;
ae23c9
         }
ae23c9
         error_setg(errp, "Image format driver does not support resize");
ae23c9
-        return -ENOTSUP;
ae23c9
+        ret = -ENOTSUP;
ae23c9
+        goto out;
ae23c9
     }
ae23c9
     if (bs->read_only) {
ae23c9
         error_setg(errp, "Image is read-only");
ae23c9
-        return -EACCES;
ae23c9
+        ret = -EACCES;
ae23c9
+        goto out;
ae23c9
     }
ae23c9
 
ae23c9
     assert(!(bs->open_flags & BDRV_O_INACTIVE));
ae23c9
 
ae23c9
-    ret = drv->bdrv_truncate(bs, offset, prealloc, errp);
ae23c9
+    ret = drv->bdrv_co_truncate(bs, offset, prealloc, errp);
ae23c9
     if (ret < 0) {
ae23c9
-        return ret;
ae23c9
+        goto out;
ae23c9
     }
ae23c9
     ret = refresh_total_sectors(bs, offset >> BDRV_SECTOR_BITS);
ae23c9
     if (ret < 0) {
ae23c9
@@ -3784,9 +3789,51 @@ int bdrv_truncate(BdrvChild *child, int64_t offset, PreallocMode prealloc,
ae23c9
     bdrv_dirty_bitmap_truncate(bs, offset);
ae23c9
     bdrv_parent_cb_resize(bs);
ae23c9
     atomic_inc(&bs->write_gen);
ae23c9
+
ae23c9
+out:
ae23c9
+    bdrv_dec_in_flight(bs);
ae23c9
     return ret;
ae23c9
 }
ae23c9
 
ae23c9
+typedef struct TruncateCo {
ae23c9
+    BdrvChild *child;
ae23c9
+    int64_t offset;
ae23c9
+    PreallocMode prealloc;
ae23c9
+    Error **errp;
ae23c9
+    int ret;
ae23c9
+} TruncateCo;
ae23c9
+
ae23c9
+static void coroutine_fn bdrv_truncate_co_entry(void *opaque)
ae23c9
+{
ae23c9
+    TruncateCo *tco = opaque;
ae23c9
+    tco->ret = bdrv_co_truncate(tco->child, tco->offset, tco->prealloc,
ae23c9
+                                tco->errp);
ae23c9
+}
ae23c9
+
ae23c9
+int bdrv_truncate(BdrvChild *child, int64_t offset, PreallocMode prealloc,
ae23c9
+                  Error **errp)
ae23c9
+{
ae23c9
+    Coroutine *co;
ae23c9
+    TruncateCo tco = {
ae23c9
+        .child      = child,
ae23c9
+        .offset     = offset,
ae23c9
+        .prealloc   = prealloc,
ae23c9
+        .errp       = errp,
ae23c9
+        .ret        = NOT_DONE,
ae23c9
+    };
ae23c9
+
ae23c9
+    if (qemu_in_coroutine()) {
ae23c9
+        /* Fast-path if already in coroutine context */
ae23c9
+        bdrv_truncate_co_entry(&tco;;
ae23c9
+    } else {
ae23c9
+        co = qemu_coroutine_create(bdrv_truncate_co_entry, &tco;;
ae23c9
+        qemu_coroutine_enter(co);
ae23c9
+        BDRV_POLL_WHILE(child->bs, tco.ret == NOT_DONE);
ae23c9
+    }
ae23c9
+
ae23c9
+    return tco.ret;
ae23c9
+}
ae23c9
+
ae23c9
 /**
ae23c9
  * Length of a allocated file in bytes. Sparse files are counted by actual
ae23c9
  * allocated space. Return < 0 if error or unknown.
ae23c9
diff --git a/block/copy-on-read.c b/block/copy-on-read.c
ae23c9
index 6a97208..1dcdaee 100644
ae23c9
--- a/block/copy-on-read.c
ae23c9
+++ b/block/copy-on-read.c
ae23c9
@@ -80,10 +80,10 @@ static int64_t cor_getlength(BlockDriverState *bs)
ae23c9
 }
ae23c9
 
ae23c9
 
ae23c9
-static int cor_truncate(BlockDriverState *bs, int64_t offset,
ae23c9
-                        PreallocMode prealloc, Error **errp)
ae23c9
+static int coroutine_fn cor_co_truncate(BlockDriverState *bs, int64_t offset,
ae23c9
+                                        PreallocMode prealloc, Error **errp)
ae23c9
 {
ae23c9
-    return bdrv_truncate(bs->file, offset, prealloc, errp);
ae23c9
+    return bdrv_co_truncate(bs->file, offset, prealloc, errp);
ae23c9
 }
ae23c9
 
ae23c9
 
ae23c9
@@ -147,7 +147,7 @@ BlockDriver bdrv_copy_on_read = {
ae23c9
     .bdrv_child_perm                    = cor_child_perm,
ae23c9
 
ae23c9
     .bdrv_getlength                     = cor_getlength,
ae23c9
-    .bdrv_truncate                      = cor_truncate,
ae23c9
+    .bdrv_co_truncate                   = cor_co_truncate,
ae23c9
 
ae23c9
     .bdrv_co_preadv                     = cor_co_preadv,
ae23c9
     .bdrv_co_pwritev                    = cor_co_pwritev,
ae23c9
diff --git a/block/crypto.c b/block/crypto.c
ae23c9
index f5151f4..02f04f3 100644
ae23c9
--- a/block/crypto.c
ae23c9
+++ b/block/crypto.c
ae23c9
@@ -357,8 +357,9 @@ static int block_crypto_co_create_generic(BlockDriverState *bs,
ae23c9
     return ret;
ae23c9
 }
ae23c9
 
ae23c9
-static int block_crypto_truncate(BlockDriverState *bs, int64_t offset,
ae23c9
-                                 PreallocMode prealloc, Error **errp)
ae23c9
+static int coroutine_fn
ae23c9
+block_crypto_co_truncate(BlockDriverState *bs, int64_t offset,
ae23c9
+                         PreallocMode prealloc, Error **errp)
ae23c9
 {
ae23c9
     BlockCrypto *crypto = bs->opaque;
ae23c9
     uint64_t payload_offset =
ae23c9
@@ -371,7 +372,7 @@ static int block_crypto_truncate(BlockDriverState *bs, int64_t offset,
ae23c9
 
ae23c9
     offset += payload_offset;
ae23c9
 
ae23c9
-    return bdrv_truncate(bs->file, offset, prealloc, errp);
ae23c9
+    return bdrv_co_truncate(bs->file, offset, prealloc, errp);
ae23c9
 }
ae23c9
 
ae23c9
 static void block_crypto_close(BlockDriverState *bs)
ae23c9
@@ -700,7 +701,7 @@ BlockDriver bdrv_crypto_luks = {
ae23c9
     .bdrv_child_perm    = bdrv_format_default_perms,
ae23c9
     .bdrv_co_create     = block_crypto_co_create_luks,
ae23c9
     .bdrv_co_create_opts = block_crypto_co_create_opts_luks,
ae23c9
-    .bdrv_truncate      = block_crypto_truncate,
ae23c9
+    .bdrv_co_truncate   = block_crypto_co_truncate,
ae23c9
     .create_opts        = &block_crypto_create_opts_luks,
ae23c9
 
ae23c9
     .bdrv_reopen_prepare = block_crypto_reopen_prepare,
ae23c9
diff --git a/block/file-posix.c b/block/file-posix.c
ae23c9
index cbf7c11..f8488ec 100644
ae23c9
--- a/block/file-posix.c
ae23c9
+++ b/block/file-posix.c
ae23c9
@@ -1832,8 +1832,8 @@ out:
ae23c9
     return result;
ae23c9
 }
ae23c9
 
ae23c9
-static int raw_truncate(BlockDriverState *bs, int64_t offset,
ae23c9
-                        PreallocMode prealloc, Error **errp)
ae23c9
+static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset,
ae23c9
+                                        PreallocMode prealloc, Error **errp)
ae23c9
 {
ae23c9
     BDRVRawState *s = bs->opaque;
ae23c9
     struct stat st;
ae23c9
@@ -2474,7 +2474,7 @@ BlockDriver bdrv_file = {
ae23c9
     .bdrv_io_plug = raw_aio_plug,
ae23c9
     .bdrv_io_unplug = raw_aio_unplug,
ae23c9
 
ae23c9
-    .bdrv_truncate = raw_truncate,
ae23c9
+    .bdrv_co_truncate = raw_co_truncate,
ae23c9
     .bdrv_getlength = raw_getlength,
ae23c9
     .bdrv_get_info = raw_get_info,
ae23c9
     .bdrv_get_allocated_file_size
ae23c9
@@ -2953,7 +2953,7 @@ static BlockDriver bdrv_host_device = {
ae23c9
     .bdrv_io_plug = raw_aio_plug,
ae23c9
     .bdrv_io_unplug = raw_aio_unplug,
ae23c9
 
ae23c9
-    .bdrv_truncate      = raw_truncate,
ae23c9
+    .bdrv_co_truncate       = raw_co_truncate,
ae23c9
     .bdrv_getlength	= raw_getlength,
ae23c9
     .bdrv_get_info = raw_get_info,
ae23c9
     .bdrv_get_allocated_file_size
ae23c9
@@ -3074,7 +3074,7 @@ static BlockDriver bdrv_host_cdrom = {
ae23c9
     .bdrv_io_plug = raw_aio_plug,
ae23c9
     .bdrv_io_unplug = raw_aio_unplug,
ae23c9
 
ae23c9
-    .bdrv_truncate      = raw_truncate,
ae23c9
+    .bdrv_co_truncate    = raw_co_truncate,
ae23c9
     .bdrv_getlength      = raw_getlength,
ae23c9
     .has_variable_length = true,
ae23c9
     .bdrv_get_allocated_file_size
ae23c9
@@ -3204,7 +3204,7 @@ static BlockDriver bdrv_host_cdrom = {
ae23c9
     .bdrv_io_plug = raw_aio_plug,
ae23c9
     .bdrv_io_unplug = raw_aio_unplug,
ae23c9
 
ae23c9
-    .bdrv_truncate      = raw_truncate,
ae23c9
+    .bdrv_co_truncate    = raw_co_truncate,
ae23c9
     .bdrv_getlength      = raw_getlength,
ae23c9
     .has_variable_length = true,
ae23c9
     .bdrv_get_allocated_file_size
ae23c9
diff --git a/block/file-win32.c b/block/file-win32.c
ae23c9
index 2e2f746..6573338 100644
ae23c9
--- a/block/file-win32.c
ae23c9
+++ b/block/file-win32.c
ae23c9
@@ -463,8 +463,8 @@ static void raw_close(BlockDriverState *bs)
ae23c9
     }
ae23c9
 }
ae23c9
 
ae23c9
-static int raw_truncate(BlockDriverState *bs, int64_t offset,
ae23c9
-                        PreallocMode prealloc, Error **errp)
ae23c9
+static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset,
ae23c9
+                                        PreallocMode prealloc, Error **errp)
ae23c9
 {
ae23c9
     BDRVRawState *s = bs->opaque;
ae23c9
     LONG low, high;
ae23c9
@@ -636,7 +636,7 @@ BlockDriver bdrv_file = {
ae23c9
     .bdrv_aio_writev    = raw_aio_writev,
ae23c9
     .bdrv_aio_flush     = raw_aio_flush,
ae23c9
 
ae23c9
-    .bdrv_truncate	= raw_truncate,
ae23c9
+    .bdrv_co_truncate   = raw_co_truncate,
ae23c9
     .bdrv_getlength	= raw_getlength,
ae23c9
     .bdrv_get_allocated_file_size
ae23c9
                         = raw_get_allocated_file_size,
ae23c9
diff --git a/block/gluster.c b/block/gluster.c
ae23c9
index 418bb73..cecfe09 100644
ae23c9
--- a/block/gluster.c
ae23c9
+++ b/block/gluster.c
ae23c9
@@ -1177,8 +1177,10 @@ static coroutine_fn int qemu_gluster_co_rw(BlockDriverState *bs,
ae23c9
     return acb.ret;
ae23c9
 }
ae23c9
 
ae23c9
-static int qemu_gluster_truncate(BlockDriverState *bs, int64_t offset,
ae23c9
-                                 PreallocMode prealloc, Error **errp)
ae23c9
+static coroutine_fn int qemu_gluster_co_truncate(BlockDriverState *bs,
ae23c9
+                                                 int64_t offset,
ae23c9
+                                                 PreallocMode prealloc,
ae23c9
+                                                 Error **errp)
ae23c9
 {
ae23c9
     BDRVGlusterState *s = bs->opaque;
ae23c9
     return qemu_gluster_do_truncate(s->fd, offset, prealloc, errp);
ae23c9
@@ -1497,7 +1499,7 @@ static BlockDriver bdrv_gluster = {
ae23c9
     .bdrv_co_create_opts          = qemu_gluster_co_create_opts,
ae23c9
     .bdrv_getlength               = qemu_gluster_getlength,
ae23c9
     .bdrv_get_allocated_file_size = qemu_gluster_allocated_file_size,
ae23c9
-    .bdrv_truncate                = qemu_gluster_truncate,
ae23c9
+    .bdrv_co_truncate             = qemu_gluster_co_truncate,
ae23c9
     .bdrv_co_readv                = qemu_gluster_co_readv,
ae23c9
     .bdrv_co_writev               = qemu_gluster_co_writev,
ae23c9
     .bdrv_co_flush_to_disk        = qemu_gluster_co_flush_to_disk,
ae23c9
@@ -1526,7 +1528,7 @@ static BlockDriver bdrv_gluster_tcp = {
ae23c9
     .bdrv_co_create_opts          = qemu_gluster_co_create_opts,
ae23c9
     .bdrv_getlength               = qemu_gluster_getlength,
ae23c9
     .bdrv_get_allocated_file_size = qemu_gluster_allocated_file_size,
ae23c9
-    .bdrv_truncate                = qemu_gluster_truncate,
ae23c9
+    .bdrv_co_truncate             = qemu_gluster_co_truncate,
ae23c9
     .bdrv_co_readv                = qemu_gluster_co_readv,
ae23c9
     .bdrv_co_writev               = qemu_gluster_co_writev,
ae23c9
     .bdrv_co_flush_to_disk        = qemu_gluster_co_flush_to_disk,
ae23c9
@@ -1555,7 +1557,7 @@ static BlockDriver bdrv_gluster_unix = {
ae23c9
     .bdrv_co_create_opts          = qemu_gluster_co_create_opts,
ae23c9
     .bdrv_getlength               = qemu_gluster_getlength,
ae23c9
     .bdrv_get_allocated_file_size = qemu_gluster_allocated_file_size,
ae23c9
-    .bdrv_truncate                = qemu_gluster_truncate,
ae23c9
+    .bdrv_co_truncate             = qemu_gluster_co_truncate,
ae23c9
     .bdrv_co_readv                = qemu_gluster_co_readv,
ae23c9
     .bdrv_co_writev               = qemu_gluster_co_writev,
ae23c9
     .bdrv_co_flush_to_disk        = qemu_gluster_co_flush_to_disk,
ae23c9
@@ -1590,7 +1592,7 @@ static BlockDriver bdrv_gluster_rdma = {
ae23c9
     .bdrv_co_create_opts          = qemu_gluster_co_create_opts,
ae23c9
     .bdrv_getlength               = qemu_gluster_getlength,
ae23c9
     .bdrv_get_allocated_file_size = qemu_gluster_allocated_file_size,
ae23c9
-    .bdrv_truncate                = qemu_gluster_truncate,
ae23c9
+    .bdrv_co_truncate             = qemu_gluster_co_truncate,
ae23c9
     .bdrv_co_readv                = qemu_gluster_co_readv,
ae23c9
     .bdrv_co_writev               = qemu_gluster_co_writev,
ae23c9
     .bdrv_co_flush_to_disk        = qemu_gluster_co_flush_to_disk,
ae23c9
diff --git a/block/iscsi.c b/block/iscsi.c
ae23c9
index 751884d..5047e83 100644
ae23c9
--- a/block/iscsi.c
ae23c9
+++ b/block/iscsi.c
ae23c9
@@ -2085,8 +2085,8 @@ static void iscsi_reopen_commit(BDRVReopenState *reopen_state)
ae23c9
     }
ae23c9
 }
ae23c9
 
ae23c9
-static int iscsi_truncate(BlockDriverState *bs, int64_t offset,
ae23c9
-                          PreallocMode prealloc, Error **errp)
ae23c9
+static int coroutine_fn iscsi_co_truncate(BlockDriverState *bs, int64_t offset,
ae23c9
+                                          PreallocMode prealloc, Error **errp)
ae23c9
 {
ae23c9
     IscsiLun *iscsilun = bs->opaque;
ae23c9
     Error *local_err = NULL;
ae23c9
@@ -2431,7 +2431,7 @@ static BlockDriver bdrv_iscsi = {
ae23c9
 
ae23c9
     .bdrv_getlength  = iscsi_getlength,
ae23c9
     .bdrv_get_info   = iscsi_get_info,
ae23c9
-    .bdrv_truncate   = iscsi_truncate,
ae23c9
+    .bdrv_co_truncate    = iscsi_co_truncate,
ae23c9
     .bdrv_refresh_limits = iscsi_refresh_limits,
ae23c9
 
ae23c9
     .bdrv_co_block_status  = iscsi_co_block_status,
ae23c9
@@ -2468,7 +2468,7 @@ static BlockDriver bdrv_iser = {
ae23c9
 
ae23c9
     .bdrv_getlength  = iscsi_getlength,
ae23c9
     .bdrv_get_info   = iscsi_get_info,
ae23c9
-    .bdrv_truncate   = iscsi_truncate,
ae23c9
+    .bdrv_co_truncate    = iscsi_co_truncate,
ae23c9
     .bdrv_refresh_limits = iscsi_refresh_limits,
ae23c9
 
ae23c9
     .bdrv_co_block_status  = iscsi_co_block_status,
ae23c9
diff --git a/block/nfs.c b/block/nfs.c
ae23c9
index 743ca04..eab1a2c 100644
ae23c9
--- a/block/nfs.c
ae23c9
+++ b/block/nfs.c
ae23c9
@@ -743,8 +743,9 @@ static int64_t nfs_get_allocated_file_size(BlockDriverState *bs)
ae23c9
     return (task.ret < 0 ? task.ret : st.st_blocks * 512);
ae23c9
 }
ae23c9
 
ae23c9
-static int nfs_file_truncate(BlockDriverState *bs, int64_t offset,
ae23c9
-                             PreallocMode prealloc, Error **errp)
ae23c9
+static int coroutine_fn
ae23c9
+nfs_file_co_truncate(BlockDriverState *bs, int64_t offset,
ae23c9
+                     PreallocMode prealloc, Error **errp)
ae23c9
 {
ae23c9
     NFSClient *client = bs->opaque;
ae23c9
     int ret;
ae23c9
@@ -873,7 +874,7 @@ static BlockDriver bdrv_nfs = {
ae23c9
 
ae23c9
     .bdrv_has_zero_init             = nfs_has_zero_init,
ae23c9
     .bdrv_get_allocated_file_size   = nfs_get_allocated_file_size,
ae23c9
-    .bdrv_truncate                  = nfs_file_truncate,
ae23c9
+    .bdrv_co_truncate               = nfs_file_co_truncate,
ae23c9
 
ae23c9
     .bdrv_file_open                 = nfs_file_open,
ae23c9
     .bdrv_close                     = nfs_file_close,
ae23c9
diff --git a/block/qcow2.c b/block/qcow2.c
ae23c9
index dbd448c..c5c6ae9 100644
ae23c9
--- a/block/qcow2.c
ae23c9
+++ b/block/qcow2.c
ae23c9
@@ -2539,15 +2539,12 @@ static void coroutine_fn preallocate_co(void *opaque)
ae23c9
     BlockDriverState *bs = params->bs;
ae23c9
     uint64_t offset = params->offset;
ae23c9
     uint64_t new_length = params->new_length;
ae23c9
-    BDRVQcow2State *s = bs->opaque;
ae23c9
     uint64_t bytes;
ae23c9
     uint64_t host_offset = 0;
ae23c9
     unsigned int cur_bytes;
ae23c9
     int ret;
ae23c9
     QCowL2Meta *meta;
ae23c9
 
ae23c9
-    qemu_co_mutex_lock(&s->lock);
ae23c9
-
ae23c9
     assert(offset <= new_length);
ae23c9
     bytes = new_length - offset;
ae23c9
 
ae23c9
@@ -2600,7 +2597,6 @@ static void coroutine_fn preallocate_co(void *opaque)
ae23c9
     ret = 0;
ae23c9
 
ae23c9
 done:
ae23c9
-    qemu_co_mutex_unlock(&s->lock);
ae23c9
     params->ret = ret;
ae23c9
 }
ae23c9
 
ae23c9
@@ -3037,7 +3033,11 @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp)
ae23c9
 
ae23c9
     /* And if we're supposed to preallocate metadata, do that now */
ae23c9
     if (qcow2_opts->preallocation != PREALLOC_MODE_OFF) {
ae23c9
+        BDRVQcow2State *s = blk_bs(blk)->opaque;
ae23c9
+        qemu_co_mutex_lock(&s->lock);
ae23c9
         ret = preallocate(blk_bs(blk), 0, qcow2_opts->size);
ae23c9
+        qemu_co_mutex_unlock(&s->lock);
ae23c9
+
ae23c9
         if (ret < 0) {
ae23c9
             error_setg_errno(errp, -ret, "Could not preallocate metadata");
ae23c9
             goto out;
ae23c9
@@ -3434,8 +3434,8 @@ fail:
ae23c9
     return ret;
ae23c9
 }
ae23c9
 
ae23c9
-static int qcow2_truncate(BlockDriverState *bs, int64_t offset,
ae23c9
-                          PreallocMode prealloc, Error **errp)
ae23c9
+static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
ae23c9
+                                          PreallocMode prealloc, Error **errp)
ae23c9
 {
ae23c9
     BDRVQcow2State *s = bs->opaque;
ae23c9
     uint64_t old_length;
ae23c9
@@ -3455,17 +3455,21 @@ static int qcow2_truncate(BlockDriverState *bs, int64_t offset,
ae23c9
         return -EINVAL;
ae23c9
     }
ae23c9
 
ae23c9
+    qemu_co_mutex_lock(&s->lock);
ae23c9
+
ae23c9
     /* cannot proceed if image has snapshots */
ae23c9
     if (s->nb_snapshots) {
ae23c9
         error_setg(errp, "Can't resize an image which has snapshots");
ae23c9
-        return -ENOTSUP;
ae23c9
+        ret = -ENOTSUP;
ae23c9
+        goto fail;
ae23c9
     }
ae23c9
 
ae23c9
     /* cannot proceed if image has bitmaps */
ae23c9
     if (s->nb_bitmaps) {
ae23c9
         /* TODO: resize bitmaps in the image */
ae23c9
         error_setg(errp, "Can't resize an image which has bitmaps");
ae23c9
-        return -ENOTSUP;
ae23c9
+        ret = -ENOTSUP;
ae23c9
+        goto fail;
ae23c9
     }
ae23c9
 
ae23c9
     old_length = bs->total_sectors * 512;
ae23c9
@@ -3476,7 +3480,8 @@ static int qcow2_truncate(BlockDriverState *bs, int64_t offset,
ae23c9
         if (prealloc != PREALLOC_MODE_OFF) {
ae23c9
             error_setg(errp,
ae23c9
                        "Preallocation can't be used for shrinking an image");
ae23c9
-            return -EINVAL;
ae23c9
+            ret = -EINVAL;
ae23c9
+            goto fail;
ae23c9
         }
ae23c9
 
ae23c9
         ret = qcow2_cluster_discard(bs, ROUND_UP(offset, s->cluster_size),
ae23c9
@@ -3485,40 +3490,42 @@ static int qcow2_truncate(BlockDriverState *bs, int64_t offset,
ae23c9
                                     QCOW2_DISCARD_ALWAYS, true);
ae23c9
         if (ret < 0) {
ae23c9
             error_setg_errno(errp, -ret, "Failed to discard cropped clusters");
ae23c9
-            return ret;
ae23c9
+            goto fail;
ae23c9
         }
ae23c9
 
ae23c9
         ret = qcow2_shrink_l1_table(bs, new_l1_size);
ae23c9
         if (ret < 0) {
ae23c9
             error_setg_errno(errp, -ret,
ae23c9
                              "Failed to reduce the number of L2 tables");
ae23c9
-            return ret;
ae23c9
+            goto fail;
ae23c9
         }
ae23c9
 
ae23c9
         ret = qcow2_shrink_reftable(bs);
ae23c9
         if (ret < 0) {
ae23c9
             error_setg_errno(errp, -ret,
ae23c9
                              "Failed to discard unused refblocks");
ae23c9
-            return ret;
ae23c9
+            goto fail;
ae23c9
         }
ae23c9
 
ae23c9
         old_file_size = bdrv_getlength(bs->file->bs);
ae23c9
         if (old_file_size < 0) {
ae23c9
             error_setg_errno(errp, -old_file_size,
ae23c9
                              "Failed to inquire current file length");
ae23c9
-            return old_file_size;
ae23c9
+            ret = old_file_size;
ae23c9
+            goto fail;
ae23c9
         }
ae23c9
         last_cluster = qcow2_get_last_cluster(bs, old_file_size);
ae23c9
         if (last_cluster < 0) {
ae23c9
             error_setg_errno(errp, -last_cluster,
ae23c9
                              "Failed to find the last cluster");
ae23c9
-            return last_cluster;
ae23c9
+            ret = last_cluster;
ae23c9
+            goto fail;
ae23c9
         }
ae23c9
         if ((last_cluster + 1) * s->cluster_size < old_file_size) {
ae23c9
             Error *local_err = NULL;
ae23c9
 
ae23c9
-            bdrv_truncate(bs->file, (last_cluster + 1) * s->cluster_size,
ae23c9
-                          PREALLOC_MODE_OFF, &local_err);
ae23c9
+            bdrv_co_truncate(bs->file, (last_cluster + 1) * s->cluster_size,
ae23c9
+                             PREALLOC_MODE_OFF, &local_err);
ae23c9
             if (local_err) {
ae23c9
                 warn_reportf_err(local_err,
ae23c9
                                  "Failed to truncate the tail of the image: ");
ae23c9
@@ -3528,7 +3535,7 @@ static int qcow2_truncate(BlockDriverState *bs, int64_t offset,
ae23c9
         ret = qcow2_grow_l1_table(bs, new_l1_size, true);
ae23c9
         if (ret < 0) {
ae23c9
             error_setg_errno(errp, -ret, "Failed to grow the L1 table");
ae23c9
-            return ret;
ae23c9
+            goto fail;
ae23c9
         }
ae23c9
     }
ae23c9
 
ae23c9
@@ -3540,7 +3547,7 @@ static int qcow2_truncate(BlockDriverState *bs, int64_t offset,
ae23c9
         ret = preallocate(bs, old_length, offset);
ae23c9
         if (ret < 0) {
ae23c9
             error_setg_errno(errp, -ret, "Preallocation failed");
ae23c9
-            return ret;
ae23c9
+            goto fail;
ae23c9
         }
ae23c9
         break;
ae23c9
 
ae23c9
@@ -3556,7 +3563,8 @@ static int qcow2_truncate(BlockDriverState *bs, int64_t offset,
ae23c9
         if (old_file_size < 0) {
ae23c9
             error_setg_errno(errp, -old_file_size,
ae23c9
                              "Failed to inquire current file length");
ae23c9
-            return old_file_size;
ae23c9
+            ret = old_file_size;
ae23c9
+            goto fail;
ae23c9
         }
ae23c9
         old_file_size = ROUND_UP(old_file_size, s->cluster_size);
ae23c9
 
ae23c9
@@ -3586,7 +3594,8 @@ static int qcow2_truncate(BlockDriverState *bs, int64_t offset,
ae23c9
         if (allocation_start < 0) {
ae23c9
             error_setg_errno(errp, -allocation_start,
ae23c9
                              "Failed to resize refcount structures");
ae23c9
-            return allocation_start;
ae23c9
+            ret = allocation_start;
ae23c9
+            goto fail;
ae23c9
         }
ae23c9
 
ae23c9
         clusters_allocated = qcow2_alloc_clusters_at(bs, allocation_start,
ae23c9
@@ -3594,7 +3603,8 @@ static int qcow2_truncate(BlockDriverState *bs, int64_t offset,
ae23c9
         if (clusters_allocated < 0) {
ae23c9
             error_setg_errno(errp, -clusters_allocated,
ae23c9
                              "Failed to allocate data clusters");
ae23c9
-            return clusters_allocated;
ae23c9
+            ret = clusters_allocated;
ae23c9
+            goto fail;
ae23c9
         }
ae23c9
 
ae23c9
         assert(clusters_allocated == nb_new_data_clusters);
ae23c9
@@ -3602,13 +3612,13 @@ static int qcow2_truncate(BlockDriverState *bs, int64_t offset,
ae23c9
         /* Allocate the data area */
ae23c9
         new_file_size = allocation_start +
ae23c9
                         nb_new_data_clusters * s->cluster_size;
ae23c9
-        ret = bdrv_truncate(bs->file, new_file_size, prealloc, errp);
ae23c9
+        ret = bdrv_co_truncate(bs->file, new_file_size, prealloc, errp);
ae23c9
         if (ret < 0) {
ae23c9
             error_prepend(errp, "Failed to resize underlying file: ");
ae23c9
             qcow2_free_clusters(bs, allocation_start,
ae23c9
                                 nb_new_data_clusters * s->cluster_size,
ae23c9
                                 QCOW2_DISCARD_OTHER);
ae23c9
-            return ret;
ae23c9
+            goto fail;
ae23c9
         }
ae23c9
 
ae23c9
         /* Create the necessary L2 entries */
ae23c9
@@ -3631,7 +3641,7 @@ static int qcow2_truncate(BlockDriverState *bs, int64_t offset,
ae23c9
                 qcow2_free_clusters(bs, host_offset,
ae23c9
                                     nb_new_data_clusters * s->cluster_size,
ae23c9
                                     QCOW2_DISCARD_OTHER);
ae23c9
-                return ret;
ae23c9
+                goto fail;
ae23c9
             }
ae23c9
 
ae23c9
             guest_offset += nb_clusters * s->cluster_size;
ae23c9
@@ -3647,11 +3657,11 @@ static int qcow2_truncate(BlockDriverState *bs, int64_t offset,
ae23c9
 
ae23c9
     if (prealloc != PREALLOC_MODE_OFF) {
ae23c9
         /* Flush metadata before actually changing the image size */
ae23c9
-        ret = bdrv_flush(bs);
ae23c9
+        ret = qcow2_write_caches(bs);
ae23c9
         if (ret < 0) {
ae23c9
             error_setg_errno(errp, -ret,
ae23c9
                              "Failed to flush the preallocated area to disk");
ae23c9
-            return ret;
ae23c9
+            goto fail;
ae23c9
         }
ae23c9
     }
ae23c9
 
ae23c9
@@ -3661,11 +3671,14 @@ static int qcow2_truncate(BlockDriverState *bs, int64_t offset,
ae23c9
                            &offset, sizeof(uint64_t));
ae23c9
     if (ret < 0) {
ae23c9
         error_setg_errno(errp, -ret, "Failed to update the image size");
ae23c9
-        return ret;
ae23c9
+        goto fail;
ae23c9
     }
ae23c9
 
ae23c9
     s->l1_vm_state_index = new_l1_size;
ae23c9
-    return 0;
ae23c9
+    ret = 0;
ae23c9
+fail:
ae23c9
+    qemu_co_mutex_unlock(&s->lock);
ae23c9
+    return ret;
ae23c9
 }
ae23c9
 
ae23c9
 /* XXX: put compressed sectors first, then all the cluster aligned
ae23c9
@@ -3689,7 +3702,8 @@ qcow2_co_pwritev_compressed(BlockDriverState *bs, uint64_t offset,
ae23c9
         if (cluster_offset < 0) {
ae23c9
             return cluster_offset;
ae23c9
         }
ae23c9
-        return bdrv_truncate(bs->file, cluster_offset, PREALLOC_MODE_OFF, NULL);
ae23c9
+        return bdrv_co_truncate(bs->file, cluster_offset, PREALLOC_MODE_OFF,
ae23c9
+                                NULL);
ae23c9
     }
ae23c9
 
ae23c9
     if (offset_into_cluster(s, offset)) {
ae23c9
@@ -4694,7 +4708,7 @@ BlockDriver bdrv_qcow2 = {
ae23c9
     .bdrv_co_pdiscard       = qcow2_co_pdiscard,
ae23c9
     .bdrv_co_copy_range_from = qcow2_co_copy_range_from,
ae23c9
     .bdrv_co_copy_range_to  = qcow2_co_copy_range_to,
ae23c9
-    .bdrv_truncate          = qcow2_truncate,
ae23c9
+    .bdrv_co_truncate       = qcow2_co_truncate,
ae23c9
     .bdrv_co_pwritev_compressed = qcow2_co_pwritev_compressed,
ae23c9
     .bdrv_make_empty        = qcow2_make_empty,
ae23c9
 
ae23c9
diff --git a/block/qed.c b/block/qed.c
ae23c9
index 4c5d7e8..34cccea 100644
ae23c9
--- a/block/qed.c
ae23c9
+++ b/block/qed.c
ae23c9
@@ -1466,8 +1466,10 @@ static int coroutine_fn bdrv_qed_co_pwrite_zeroes(BlockDriverState *bs,
ae23c9
                           QED_AIOCB_WRITE | QED_AIOCB_ZERO);
ae23c9
 }
ae23c9
 
ae23c9
-static int bdrv_qed_truncate(BlockDriverState *bs, int64_t offset,
ae23c9
-                             PreallocMode prealloc, Error **errp)
ae23c9
+static int coroutine_fn bdrv_qed_co_truncate(BlockDriverState *bs,
ae23c9
+                                             int64_t offset,
ae23c9
+                                             PreallocMode prealloc,
ae23c9
+                                             Error **errp)
ae23c9
 {
ae23c9
     BDRVQEDState *s = bs->opaque;
ae23c9
     uint64_t old_image_size;
ae23c9
@@ -1677,7 +1679,7 @@ static BlockDriver bdrv_qed = {
ae23c9
     .bdrv_co_readv            = bdrv_qed_co_readv,
ae23c9
     .bdrv_co_writev           = bdrv_qed_co_writev,
ae23c9
     .bdrv_co_pwrite_zeroes    = bdrv_qed_co_pwrite_zeroes,
ae23c9
-    .bdrv_truncate            = bdrv_qed_truncate,
ae23c9
+    .bdrv_co_truncate         = bdrv_qed_co_truncate,
ae23c9
     .bdrv_getlength           = bdrv_qed_getlength,
ae23c9
     .bdrv_get_info            = bdrv_qed_get_info,
ae23c9
     .bdrv_refresh_limits      = bdrv_qed_refresh_limits,
ae23c9
diff --git a/block/raw-format.c b/block/raw-format.c
ae23c9
index f2e468d..b78da56 100644
ae23c9
--- a/block/raw-format.c
ae23c9
+++ b/block/raw-format.c
ae23c9
@@ -366,8 +366,8 @@ static void raw_refresh_limits(BlockDriverState *bs, Error **errp)
ae23c9
     }
ae23c9
 }
ae23c9
 
ae23c9
-static int raw_truncate(BlockDriverState *bs, int64_t offset,
ae23c9
-                        PreallocMode prealloc, Error **errp)
ae23c9
+static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset,
ae23c9
+                                        PreallocMode prealloc, Error **errp)
ae23c9
 {
ae23c9
     BDRVRawState *s = bs->opaque;
ae23c9
 
ae23c9
@@ -383,7 +383,7 @@ static int raw_truncate(BlockDriverState *bs, int64_t offset,
ae23c9
 
ae23c9
     s->size = offset;
ae23c9
     offset += s->offset;
ae23c9
-    return bdrv_truncate(bs->file, offset, prealloc, errp);
ae23c9
+    return bdrv_co_truncate(bs->file, offset, prealloc, errp);
ae23c9
 }
ae23c9
 
ae23c9
 static void raw_eject(BlockDriverState *bs, bool eject_flag)
ae23c9
@@ -545,7 +545,7 @@ BlockDriver bdrv_raw = {
ae23c9
     .bdrv_co_block_status = &raw_co_block_status,
ae23c9
     .bdrv_co_copy_range_from = &raw_co_copy_range_from,
ae23c9
     .bdrv_co_copy_range_to  = &raw_co_copy_range_to,
ae23c9
-    .bdrv_truncate        = &raw_truncate,
ae23c9
+    .bdrv_co_truncate     = &raw_co_truncate,
ae23c9
     .bdrv_getlength       = &raw_getlength,
ae23c9
     .has_variable_length  = true,
ae23c9
     .bdrv_measure         = &raw_measure,
ae23c9
diff --git a/block/rbd.c b/block/rbd.c
ae23c9
index 3242bcd..b93046b 100644
ae23c9
--- a/block/rbd.c
ae23c9
+++ b/block/rbd.c
ae23c9
@@ -987,8 +987,10 @@ static int64_t qemu_rbd_getlength(BlockDriverState *bs)
ae23c9
     return info.size;
ae23c9
 }
ae23c9
 
ae23c9
-static int qemu_rbd_truncate(BlockDriverState *bs, int64_t offset,
ae23c9
-                             PreallocMode prealloc, Error **errp)
ae23c9
+static int coroutine_fn qemu_rbd_co_truncate(BlockDriverState *bs,
ae23c9
+                                             int64_t offset,
ae23c9
+                                             PreallocMode prealloc,
ae23c9
+                                             Error **errp)
ae23c9
 {
ae23c9
     BDRVRBDState *s = bs->opaque;
ae23c9
     int r;
ae23c9
@@ -1180,7 +1182,7 @@ static BlockDriver bdrv_rbd = {
ae23c9
     .bdrv_get_info          = qemu_rbd_getinfo,
ae23c9
     .create_opts            = &qemu_rbd_create_opts,
ae23c9
     .bdrv_getlength         = qemu_rbd_getlength,
ae23c9
-    .bdrv_truncate          = qemu_rbd_truncate,
ae23c9
+    .bdrv_co_truncate       = qemu_rbd_co_truncate,
ae23c9
     .protocol_name          = "rbd",
ae23c9
 
ae23c9
     .bdrv_aio_readv         = qemu_rbd_aio_readv,
ae23c9
diff --git a/block/sheepdog.c b/block/sheepdog.c
ae23c9
index 933880c..14165d3 100644
ae23c9
--- a/block/sheepdog.c
ae23c9
+++ b/block/sheepdog.c
ae23c9
@@ -2294,8 +2294,8 @@ static int64_t sd_getlength(BlockDriverState *bs)
ae23c9
     return s->inode.vdi_size;
ae23c9
 }
ae23c9
 
ae23c9
-static int sd_truncate(BlockDriverState *bs, int64_t offset,
ae23c9
-                       PreallocMode prealloc, Error **errp)
ae23c9
+static int coroutine_fn sd_co_truncate(BlockDriverState *bs, int64_t offset,
ae23c9
+                                       PreallocMode prealloc, Error **errp)
ae23c9
 {
ae23c9
     BDRVSheepdogState *s = bs->opaque;
ae23c9
     int ret, fd;
ae23c9
@@ -2609,7 +2609,7 @@ static coroutine_fn int sd_co_writev(BlockDriverState *bs, int64_t sector_num,
ae23c9
     BDRVSheepdogState *s = bs->opaque;
ae23c9
 
ae23c9
     if (offset > s->inode.vdi_size) {
ae23c9
-        ret = sd_truncate(bs, offset, PREALLOC_MODE_OFF, NULL);
ae23c9
+        ret = sd_co_truncate(bs, offset, PREALLOC_MODE_OFF, NULL);
ae23c9
         if (ret < 0) {
ae23c9
             return ret;
ae23c9
         }
ae23c9
@@ -3229,7 +3229,7 @@ static BlockDriver bdrv_sheepdog = {
ae23c9
     .bdrv_has_zero_init           = bdrv_has_zero_init_1,
ae23c9
     .bdrv_getlength               = sd_getlength,
ae23c9
     .bdrv_get_allocated_file_size = sd_get_allocated_file_size,
ae23c9
-    .bdrv_truncate                = sd_truncate,
ae23c9
+    .bdrv_co_truncate             = sd_co_truncate,
ae23c9
 
ae23c9
     .bdrv_co_readv                = sd_co_readv,
ae23c9
     .bdrv_co_writev               = sd_co_writev,
ae23c9
@@ -3266,7 +3266,7 @@ static BlockDriver bdrv_sheepdog_tcp = {
ae23c9
     .bdrv_has_zero_init           = bdrv_has_zero_init_1,
ae23c9
     .bdrv_getlength               = sd_getlength,
ae23c9
     .bdrv_get_allocated_file_size = sd_get_allocated_file_size,
ae23c9
-    .bdrv_truncate                = sd_truncate,
ae23c9
+    .bdrv_co_truncate             = sd_co_truncate,
ae23c9
 
ae23c9
     .bdrv_co_readv                = sd_co_readv,
ae23c9
     .bdrv_co_writev               = sd_co_writev,
ae23c9
@@ -3303,7 +3303,7 @@ static BlockDriver bdrv_sheepdog_unix = {
ae23c9
     .bdrv_has_zero_init           = bdrv_has_zero_init_1,
ae23c9
     .bdrv_getlength               = sd_getlength,
ae23c9
     .bdrv_get_allocated_file_size = sd_get_allocated_file_size,
ae23c9
-    .bdrv_truncate                = sd_truncate,
ae23c9
+    .bdrv_co_truncate             = sd_co_truncate,
ae23c9
 
ae23c9
     .bdrv_co_readv                = sd_co_readv,
ae23c9
     .bdrv_co_writev               = sd_co_writev,
ae23c9
diff --git a/block/ssh.c b/block/ssh.c
ae23c9
index aab6996..6a55d82 100644
ae23c9
--- a/block/ssh.c
ae23c9
+++ b/block/ssh.c
ae23c9
@@ -1241,8 +1241,8 @@ static int64_t ssh_getlength(BlockDriverState *bs)
ae23c9
     return length;
ae23c9
 }
ae23c9
 
ae23c9
-static int ssh_truncate(BlockDriverState *bs, int64_t offset,
ae23c9
-                        PreallocMode prealloc, Error **errp)
ae23c9
+static int coroutine_fn ssh_co_truncate(BlockDriverState *bs, int64_t offset,
ae23c9
+                                        PreallocMode prealloc, Error **errp)
ae23c9
 {
ae23c9
     BDRVSSHState *s = bs->opaque;
ae23c9
 
ae23c9
@@ -1277,7 +1277,7 @@ static BlockDriver bdrv_ssh = {
ae23c9
     .bdrv_co_readv                = ssh_co_readv,
ae23c9
     .bdrv_co_writev               = ssh_co_writev,
ae23c9
     .bdrv_getlength               = ssh_getlength,
ae23c9
-    .bdrv_truncate                = ssh_truncate,
ae23c9
+    .bdrv_co_truncate             = ssh_co_truncate,
ae23c9
     .bdrv_co_flush_to_disk        = ssh_co_flush,
ae23c9
     .create_opts                  = &ssh_create_opts,
ae23c9
 };
ae23c9
diff --git a/include/block/block.h b/include/block/block.h
ae23c9
index e677080..c3cfb40 100644
ae23c9
--- a/include/block/block.h
ae23c9
+++ b/include/block/block.h
ae23c9
@@ -300,8 +300,12 @@ int coroutine_fn bdrv_co_pwrite_zeroes(BdrvChild *child, int64_t offset,
ae23c9
 BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs,
ae23c9
     const char *backing_file);
ae23c9
 void bdrv_refresh_filename(BlockDriverState *bs);
ae23c9
+
ae23c9
+int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset,
ae23c9
+                                  PreallocMode prealloc, Error **errp);
ae23c9
 int bdrv_truncate(BdrvChild *child, int64_t offset, PreallocMode prealloc,
ae23c9
                   Error **errp);
ae23c9
+
ae23c9
 int64_t bdrv_nb_sectors(BlockDriverState *bs);
ae23c9
 int64_t bdrv_getlength(BlockDriverState *bs);
ae23c9
 int64_t bdrv_get_allocated_file_size(BlockDriverState *bs);
ae23c9
diff --git a/include/block/block_int.h b/include/block/block_int.h
ae23c9
index 3da86a7..46b2f87 100644
ae23c9
--- a/include/block/block_int.h
ae23c9
+++ b/include/block/block_int.h
ae23c9
@@ -291,8 +291,8 @@ struct BlockDriver {
ae23c9
      * bdrv_parse_filename.
ae23c9
      */
ae23c9
     const char *protocol_name;
ae23c9
-    int (*bdrv_truncate)(BlockDriverState *bs, int64_t offset,
ae23c9
-                         PreallocMode prealloc, Error **errp);
ae23c9
+    int coroutine_fn (*bdrv_co_truncate)(BlockDriverState *bs, int64_t offset,
ae23c9
+                                         PreallocMode prealloc, Error **errp);
ae23c9
 
ae23c9
     int64_t (*bdrv_getlength)(BlockDriverState *bs);
ae23c9
     bool has_variable_length;
ae23c9
-- 
ae23c9
1.8.3.1
ae23c9