Commit 2afc4e3d authored by Peter Maydell's avatar Peter Maydell
Browse files

Merge remote-tracking branch 'remotes/maxreitz/tags/pull-block-2018-06-11' into staging



Block patches:
- Various bug fixes
- Removal of qemu-img convert's deprecated -s option
- qemu-io now exits with an error when a command failed

# gpg: Signature made Mon 11 Jun 2018 15:23:42 BST
# gpg:                using RSA key F407DB0061D5CF40
# gpg: Good signature from "Max Reitz <mreitz@redhat.com>"
# Primary key fingerprint: 91BE B60A 30DB 3E88 57D1  1829 F407 DB00 61D5 CF40

* remotes/maxreitz/tags/pull-block-2018-06-11: (29 commits)
  iotests: Add case for a corrupted inactive image
  qcow2: Do not mark inactive images corrupt
  block: Make bdrv_is_writable() public
  throttle: Fix crash on reopen
  block/qcow2-bitmap: fix free_bitmap_clusters
  qemu-img: Remove deprecated -s snapshot_id_or_name option
  iotests: Fix 219's timing
  iotests: improve pause_job
  iotests: Test post-backing convert target behavior
  qemu-img: Special post-backing convert handling
  iotests: Add test for rebasing with relative paths
  qemu-img: Resolve relative backing paths in rebase
  iotests: Let 216 make use of qemu-io's exit code
  iotests.py: Add qemu_io_silent
  qemu-io: Exit with error when a command failed
  qemu-io: Let command functions return error code
  qemu-io: Drop command functions' return values
  iotests: Repairing error during snapshot deletion
  qcow2: Repair OFLAG_COPIED when fixing leaks
  iotests: Rework 113
  ...

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents 9f55925b c50abd17
Loading
Loading
Loading
Loading
+20 −5
Original line number Diff line number Diff line
@@ -1620,13 +1620,24 @@ static int bdrv_reopen_get_flags(BlockReopenQueue *q, BlockDriverState *bs)

/* Returns whether the image file can be written to after the reopen queue @q
 * has been successfully applied, or right now if @q is NULL. */
static bool bdrv_is_writable(BlockDriverState *bs, BlockReopenQueue *q)
static bool bdrv_is_writable_after_reopen(BlockDriverState *bs,
                                          BlockReopenQueue *q)
{
    int flags = bdrv_reopen_get_flags(q, bs);

    return (flags & (BDRV_O_RDWR | BDRV_O_INACTIVE)) == BDRV_O_RDWR;
}

/*
 * Return whether the BDS can be written to.  This is not necessarily
 * the same as !bdrv_is_read_only(bs), as inactivated images may not
 * be written to but do not count as read-only images.
 */
bool bdrv_is_writable(BlockDriverState *bs)
{
    return bdrv_is_writable_after_reopen(bs, NULL);
}

static void bdrv_child_perm(BlockDriverState *bs, BlockDriverState *child_bs,
                            BdrvChild *c, const BdrvChildRole *role,
                            BlockReopenQueue *reopen_queue,
@@ -1664,7 +1675,7 @@ static int bdrv_check_perm(BlockDriverState *bs, BlockReopenQueue *q,

    /* Write permissions never work with read-only images */
    if ((cumulative_perms & (BLK_PERM_WRITE | BLK_PERM_WRITE_UNCHANGED)) &&
        !bdrv_is_writable(bs, q))
        !bdrv_is_writable_after_reopen(bs, q))
    {
        error_setg(errp, "Block node is read-only");
        return -EPERM;
@@ -1956,7 +1967,7 @@ void bdrv_format_default_perms(BlockDriverState *bs, BdrvChild *c,
                                  &perm, &shared);

        /* Format drivers may touch metadata even if the guest doesn't write */
        if (bdrv_is_writable(bs, reopen_queue)) {
        if (bdrv_is_writable_after_reopen(bs, reopen_queue)) {
            perm |= BLK_PERM_WRITE | BLK_PERM_RESIZE;
        }

@@ -4996,15 +5007,19 @@ void bdrv_remove_aio_context_notifier(BlockDriverState *bs,
}

int bdrv_amend_options(BlockDriverState *bs, QemuOpts *opts,
                       BlockDriverAmendStatusCB *status_cb, void *cb_opaque)
                       BlockDriverAmendStatusCB *status_cb, void *cb_opaque,
                       Error **errp)
{
    if (!bs->drv) {
        error_setg(errp, "Node is ejected");
        return -ENOMEDIUM;
    }
    if (!bs->drv->bdrv_amend_options) {
        error_setg(errp, "Block driver '%s' does not support option amendment",
                   bs->drv->format_name);
        return -ENOTSUP;
    }
    return bs->drv->bdrv_amend_options(bs, opts, status_cb, cb_opaque);
    return bs->drv->bdrv_amend_options(bs, opts, status_cb, cb_opaque, errp);
}

/* This function will be called by the bdrv_recurse_is_first_non_filter method
+49 −15
Original line number Diff line number Diff line
@@ -643,7 +643,7 @@ typedef enum {
 * file; if @unlock == true, also unlock the unneeded bytes.
 * @shared_perm_lock_bits is the mask of all permissions that are NOT shared.
 */
static int raw_apply_lock_bytes(BDRVRawState *s,
static int raw_apply_lock_bytes(int fd,
                                uint64_t perm_lock_bits,
                                uint64_t shared_perm_lock_bits,
                                bool unlock, Error **errp)
@@ -654,13 +654,13 @@ static int raw_apply_lock_bytes(BDRVRawState *s,
    PERM_FOREACH(i) {
        int off = RAW_LOCK_PERM_BASE + i;
        if (perm_lock_bits & (1ULL << i)) {
            ret = qemu_lock_fd(s->lock_fd, off, 1, false);
            ret = qemu_lock_fd(fd, off, 1, false);
            if (ret) {
                error_setg(errp, "Failed to lock byte %d", off);
                return ret;
            }
        } else if (unlock) {
            ret = qemu_unlock_fd(s->lock_fd, off, 1);
            ret = qemu_unlock_fd(fd, off, 1);
            if (ret) {
                error_setg(errp, "Failed to unlock byte %d", off);
                return ret;
@@ -670,13 +670,13 @@ static int raw_apply_lock_bytes(BDRVRawState *s,
    PERM_FOREACH(i) {
        int off = RAW_LOCK_SHARED_BASE + i;
        if (shared_perm_lock_bits & (1ULL << i)) {
            ret = qemu_lock_fd(s->lock_fd, off, 1, false);
            ret = qemu_lock_fd(fd, off, 1, false);
            if (ret) {
                error_setg(errp, "Failed to lock byte %d", off);
                return ret;
            }
        } else if (unlock) {
            ret = qemu_unlock_fd(s->lock_fd, off, 1);
            ret = qemu_unlock_fd(fd, off, 1);
            if (ret) {
                error_setg(errp, "Failed to unlock byte %d", off);
                return ret;
@@ -687,8 +687,7 @@ static int raw_apply_lock_bytes(BDRVRawState *s,
}

/* Check "unshared" bytes implied by @perm and ~@shared_perm in the file. */
static int raw_check_lock_bytes(BDRVRawState *s,
                                uint64_t perm, uint64_t shared_perm,
static int raw_check_lock_bytes(int fd, uint64_t perm, uint64_t shared_perm,
                                Error **errp)
{
    int ret;
@@ -698,7 +697,7 @@ static int raw_check_lock_bytes(BDRVRawState *s,
        int off = RAW_LOCK_SHARED_BASE + i;
        uint64_t p = 1ULL << i;
        if (perm & p) {
            ret = qemu_lock_fd_test(s->lock_fd, off, 1, true);
            ret = qemu_lock_fd_test(fd, off, 1, true);
            if (ret) {
                char *perm_name = bdrv_perm_names(p);
                error_setg(errp,
@@ -715,7 +714,7 @@ static int raw_check_lock_bytes(BDRVRawState *s,
        int off = RAW_LOCK_PERM_BASE + i;
        uint64_t p = 1ULL << i;
        if (!(shared_perm & p)) {
            ret = qemu_lock_fd_test(s->lock_fd, off, 1, true);
            ret = qemu_lock_fd_test(fd, off, 1, true);
            if (ret) {
                char *perm_name = bdrv_perm_names(p);
                error_setg(errp,
@@ -752,11 +751,11 @@ static int raw_handle_perm_lock(BlockDriverState *bs,

    switch (op) {
    case RAW_PL_PREPARE:
        ret = raw_apply_lock_bytes(s, s->perm | new_perm,
        ret = raw_apply_lock_bytes(s->lock_fd, s->perm | new_perm,
                                   ~s->shared_perm | ~new_shared,
                                   false, errp);
        if (!ret) {
            ret = raw_check_lock_bytes(s, new_perm, new_shared, errp);
            ret = raw_check_lock_bytes(s->lock_fd, new_perm, new_shared, errp);
            if (!ret) {
                return 0;
            }
@@ -764,7 +763,8 @@ static int raw_handle_perm_lock(BlockDriverState *bs,
        op = RAW_PL_ABORT;
        /* fall through to unlock bytes. */
    case RAW_PL_ABORT:
        raw_apply_lock_bytes(s, s->perm, ~s->shared_perm, true, &local_err);
        raw_apply_lock_bytes(s->lock_fd, s->perm, ~s->shared_perm,
                             true, &local_err);
        if (local_err) {
            /* Theoretically the above call only unlocks bytes and it cannot
             * fail. Something weird happened, report it.
@@ -773,7 +773,8 @@ static int raw_handle_perm_lock(BlockDriverState *bs,
        }
        break;
    case RAW_PL_COMMIT:
        raw_apply_lock_bytes(s, new_perm, ~new_shared, true, &local_err);
        raw_apply_lock_bytes(s->lock_fd, new_perm, ~new_shared,
                             true, &local_err);
        if (local_err) {
            /* Theoretically the above call only unlocks bytes and it cannot
             * fail. Something weird happened, report it.
@@ -2075,6 +2076,7 @@ static int raw_co_create(BlockdevCreateOptions *options, Error **errp)
{
    BlockdevCreateOptionsFile *file_opts;
    int fd;
    int perm, shared;
    int result = 0;

    /* Validate options and set default values */
@@ -2089,14 +2091,44 @@ static int raw_co_create(BlockdevCreateOptions *options, Error **errp)
    }

    /* Create file */
    fd = qemu_open(file_opts->filename, O_RDWR | O_CREAT | O_TRUNC | O_BINARY,
                   0644);
    fd = qemu_open(file_opts->filename, O_RDWR | O_CREAT | O_BINARY, 0644);
    if (fd < 0) {
        result = -errno;
        error_setg_errno(errp, -result, "Could not create file");
        goto out;
    }

    /* Take permissions: We want to discard everything, so we need
     * BLK_PERM_WRITE; and truncation to the desired size requires
     * BLK_PERM_RESIZE.
     * On the other hand, we cannot share the RESIZE permission
     * because we promise that after this function, the file has the
     * size given in the options.  If someone else were to resize it
     * concurrently, we could not guarantee that.
     * Note that after this function, we can no longer guarantee that
     * the file is not touched by a third party, so it may be resized
     * then. */
    perm = BLK_PERM_WRITE | BLK_PERM_RESIZE;
    shared = BLK_PERM_ALL & ~BLK_PERM_RESIZE;

    /* Step one: Take locks */
    result = raw_apply_lock_bytes(fd, perm, shared, false, errp);
    if (result < 0) {
        goto out_close;
    }

    /* Step two: Check that nobody else has taken conflicting locks */
    result = raw_check_lock_bytes(fd, perm, shared, errp);
    if (result < 0) {
        goto out_close;
    }

    /* Clear the file by truncating it to 0 */
    result = raw_regular_truncate(fd, 0, PREALLOC_MODE_OFF, errp);
    if (result < 0) {
        goto out_close;
    }

    if (file_opts->nocow) {
#ifdef __linux__
        /* Set NOCOW flag to solve performance issue on fs like btrfs.
@@ -2112,6 +2144,8 @@ static int raw_co_create(BlockdevCreateOptions *options, Error **errp)
#endif
    }

    /* Resize and potentially preallocate the file to the desired
     * final size */
    result = raw_regular_truncate(fd, file_opts->size, file_opts->preallocation,
                                  errp);
    if (result < 0) {
+0 −1
Original line number Diff line number Diff line
@@ -254,7 +254,6 @@ static int free_bitmap_clusters(BlockDriverState *bs, Qcow2BitmapTable *tb)

    ret = bitmap_table_load(bs, tb, &bitmap_table);
    if (ret < 0) {
        assert(bitmap_table == NULL);
        return ret;
    }

+17 −8
Original line number Diff line number Diff line
@@ -1799,6 +1799,19 @@ static int check_oflag_copied(BlockDriverState *bs, BdrvCheckResult *res,
    int ret;
    uint64_t refcount;
    int i, j;
    bool repair;

    if (fix & BDRV_FIX_ERRORS) {
        /* Always repair */
        repair = true;
    } else if (fix & BDRV_FIX_LEAKS) {
        /* Repair only if that seems safe: This function is always
         * called after the refcounts have been fixed, so the refcount
         * is accurate if that repair was successful */
        repair = !res->check_errors && !res->corruptions && !res->leaks;
    } else {
        repair = false;
    }

    for (i = 0; i < s->l1_size; i++) {
        uint64_t l1_entry = s->l1_table[i];
@@ -1818,10 +1831,8 @@ static int check_oflag_copied(BlockDriverState *bs, BdrvCheckResult *res,
        if ((refcount == 1) != ((l1_entry & QCOW_OFLAG_COPIED) != 0)) {
            fprintf(stderr, "%s OFLAG_COPIED L2 cluster: l1_index=%d "
                    "l1_entry=%" PRIx64 " refcount=%" PRIu64 "\n",
                    fix & BDRV_FIX_ERRORS ? "Repairing" :
                                            "ERROR",
                    i, l1_entry, refcount);
            if (fix & BDRV_FIX_ERRORS) {
                    repair ? "Repairing" : "ERROR", i, l1_entry, refcount);
            if (repair) {
                s->l1_table[i] = refcount == 1
                               ? l1_entry |  QCOW_OFLAG_COPIED
                               : l1_entry & ~QCOW_OFLAG_COPIED;
@@ -1862,10 +1873,8 @@ static int check_oflag_copied(BlockDriverState *bs, BdrvCheckResult *res,
                if ((refcount == 1) != ((l2_entry & QCOW_OFLAG_COPIED) != 0)) {
                    fprintf(stderr, "%s OFLAG_COPIED data cluster: "
                            "l2_entry=%" PRIx64 " refcount=%" PRIu64 "\n",
                            fix & BDRV_FIX_ERRORS ? "Repairing" :
                                                    "ERROR",
                            l2_entry, refcount);
                    if (fix & BDRV_FIX_ERRORS) {
                            repair ? "Repairing" : "ERROR", l2_entry, refcount);
                    if (repair) {
                        l2_table[j] = cpu_to_be64(refcount == 1
                                    ? l2_entry |  QCOW_OFLAG_COPIED
                                    : l2_entry & ~QCOW_OFLAG_COPIED);
+42 −32
Original line number Diff line number Diff line
@@ -4215,22 +4215,21 @@ static int qcow2_load_vmstate(BlockDriverState *bs, QEMUIOVector *qiov,
 * have to be removed.
 */
static int qcow2_downgrade(BlockDriverState *bs, int target_version,
                           BlockDriverAmendStatusCB *status_cb, void *cb_opaque)
                           BlockDriverAmendStatusCB *status_cb, void *cb_opaque,
                           Error **errp)
{
    BDRVQcow2State *s = bs->opaque;
    int current_version = s->qcow_version;
    int ret;

    if (target_version == current_version) {
        return 0;
    } else if (target_version > current_version) {
        return -EINVAL;
    } else if (target_version != 2) {
        return -EINVAL;
    }
    /* This is qcow2_downgrade(), not qcow2_upgrade() */
    assert(target_version < current_version);

    /* There are no other versions (now) that you can downgrade to */
    assert(target_version == 2);

    if (s->refcount_order != 4) {
        error_report("compat=0.10 requires refcount_bits=16");
        error_setg(errp, "compat=0.10 requires refcount_bits=16");
        return -ENOTSUP;
    }

@@ -4238,6 +4237,7 @@ static int qcow2_downgrade(BlockDriverState *bs, int target_version,
    if (s->incompatible_features & QCOW2_INCOMPAT_DIRTY) {
        ret = qcow2_mark_clean(bs);
        if (ret < 0) {
            error_setg_errno(errp, -ret, "Failed to make the image clean");
            return ret;
        }
    }
@@ -4247,6 +4247,8 @@ static int qcow2_downgrade(BlockDriverState *bs, int target_version,
     * best thing to do anyway */

    if (s->incompatible_features) {
        error_setg(errp, "Cannot downgrade an image with incompatible features "
                   "%#" PRIx64 " set", s->incompatible_features);
        return -ENOTSUP;
    }

@@ -4260,6 +4262,7 @@ static int qcow2_downgrade(BlockDriverState *bs, int target_version,

    ret = qcow2_expand_zero_clusters(bs, status_cb, cb_opaque);
    if (ret < 0) {
        error_setg_errno(errp, -ret, "Failed to turn zero into data clusters");
        return ret;
    }

@@ -4267,6 +4270,7 @@ static int qcow2_downgrade(BlockDriverState *bs, int target_version,
    ret = qcow2_update_header(bs);
    if (ret < 0) {
        s->qcow_version = current_version;
        error_setg_errno(errp, -ret, "Failed to update the image header");
        return ret;
    }
    return 0;
@@ -4344,7 +4348,8 @@ static void qcow2_amend_helper_cb(BlockDriverState *bs,

static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts,
                               BlockDriverAmendStatusCB *status_cb,
                               void *cb_opaque)
                               void *cb_opaque,
                               Error **errp)
{
    BDRVQcow2State *s = bs->opaque;
    int old_version = s->qcow_version, new_version = old_version;
@@ -4356,7 +4361,6 @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts,
    bool encrypt;
    int encformat;
    int refcount_bits = s->refcount_bits;
    Error *local_err = NULL;
    int ret;
    QemuOptDesc *desc = opts->list->desc;
    Qcow2AmendHelperCBInfo helper_cb_info;
@@ -4377,11 +4381,11 @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts,
            } else if (!strcmp(compat, "1.1")) {
                new_version = 3;
            } else {
                error_report("Unknown compatibility level %s", compat);
                error_setg(errp, "Unknown compatibility level %s", compat);
                return -EINVAL;
            }
        } else if (!strcmp(desc->name, BLOCK_OPT_PREALLOC)) {
            error_report("Cannot change preallocation mode");
            error_setg(errp, "Cannot change preallocation mode");
            return -ENOTSUP;
        } else if (!strcmp(desc->name, BLOCK_OPT_SIZE)) {
            new_size = qemu_opt_get_size(opts, BLOCK_OPT_SIZE, 0);
@@ -4394,7 +4398,8 @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts,
                                        !!s->crypto);

            if (encrypt != !!s->crypto) {
                error_report("Changing the encryption flag is not supported");
                error_setg(errp,
                           "Changing the encryption flag is not supported");
                return -ENOTSUP;
            }
        } else if (!strcmp(desc->name, BLOCK_OPT_ENCRYPT_FORMAT)) {
@@ -4402,17 +4407,19 @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts,
                qemu_opt_get(opts, BLOCK_OPT_ENCRYPT_FORMAT));

            if (encformat != s->crypt_method_header) {
                error_report("Changing the encryption format is not supported");
                error_setg(errp,
                           "Changing the encryption format is not supported");
                return -ENOTSUP;
            }
        } else if (g_str_has_prefix(desc->name, "encrypt.")) {
            error_report("Changing the encryption parameters is not supported");
            error_setg(errp,
                       "Changing the encryption parameters is not supported");
            return -ENOTSUP;
        } else if (!strcmp(desc->name, BLOCK_OPT_CLUSTER_SIZE)) {
            cluster_size = qemu_opt_get_size(opts, BLOCK_OPT_CLUSTER_SIZE,
                                             cluster_size);
            if (cluster_size != s->cluster_size) {
                error_report("Changing the cluster size is not supported");
                error_setg(errp, "Changing the cluster size is not supported");
                return -ENOTSUP;
            }
        } else if (!strcmp(desc->name, BLOCK_OPT_LAZY_REFCOUNTS)) {
@@ -4425,8 +4432,8 @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts,
            if (refcount_bits <= 0 || refcount_bits > 64 ||
                !is_power_of_2(refcount_bits))
            {
                error_report("Refcount width must be a power of two and may "
                             "not exceed 64 bits");
                error_setg(errp, "Refcount width must be a power of two and "
                           "may not exceed 64 bits");
                return -EINVAL;
            }
        } else {
@@ -4451,6 +4458,7 @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts,
        ret = qcow2_update_header(bs);
        if (ret < 0) {
            s->qcow_version = old_version;
            error_setg_errno(errp, -ret, "Failed to update the image header");
            return ret;
        }
    }
@@ -4459,7 +4467,7 @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts,
        int refcount_order = ctz32(refcount_bits);

        if (new_version < 3 && refcount_bits != 16) {
            error_report("Different refcount widths than 16 bits require "
            error_setg(errp, "Refcount widths other than 16 bits require "
                       "compatibility level 1.1 or above (use compat=1.1 or "
                       "greater)");
            return -EINVAL;
@@ -4468,9 +4476,8 @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts,
        helper_cb_info.current_operation = QCOW2_CHANGING_REFCOUNT_ORDER;
        ret = qcow2_change_refcount_order(bs, refcount_order,
                                          &qcow2_amend_helper_cb,
                                          &helper_cb_info, &local_err);
                                          &helper_cb_info, errp);
        if (ret < 0) {
            error_report_err(local_err);
            return ret;
        }
    }
@@ -4480,6 +4487,7 @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts,
                    backing_file ?: s->image_backing_file,
                    backing_format ?: s->image_backing_format);
        if (ret < 0) {
            error_setg_errno(errp, -ret, "Failed to change the backing file");
            return ret;
        }
    }
@@ -4487,14 +4495,16 @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts,
    if (s->use_lazy_refcounts != lazy_refcounts) {
        if (lazy_refcounts) {
            if (new_version < 3) {
                error_report("Lazy refcounts only supported with compatibility "
                             "level 1.1 and above (use compat=1.1 or greater)");
                error_setg(errp, "Lazy refcounts only supported with "
                           "compatibility level 1.1 and above (use compat=1.1 "
                           "or greater)");
                return -EINVAL;
            }
            s->compatible_features |= QCOW2_COMPAT_LAZY_REFCOUNTS;
            ret = qcow2_update_header(bs);
            if (ret < 0) {
                s->compatible_features &= ~QCOW2_COMPAT_LAZY_REFCOUNTS;
                error_setg_errno(errp, -ret, "Failed to update the image header");
                return ret;
            }
            s->use_lazy_refcounts = true;
@@ -4502,6 +4512,7 @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts,
            /* make image clean first */
            ret = qcow2_mark_clean(bs);
            if (ret < 0) {
                error_setg_errno(errp, -ret, "Failed to make the image clean");
                return ret;
            }
            /* now disallow lazy refcounts */
@@ -4509,6 +4520,7 @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts,
            ret = qcow2_update_header(bs);
            if (ret < 0) {
                s->compatible_features |= QCOW2_COMPAT_LAZY_REFCOUNTS;
                error_setg_errno(errp, -ret, "Failed to update the image header");
                return ret;
            }
            s->use_lazy_refcounts = false;
@@ -4517,17 +4529,15 @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts,

    if (new_size) {
        BlockBackend *blk = blk_new(BLK_PERM_RESIZE, BLK_PERM_ALL);
        ret = blk_insert_bs(blk, bs, &local_err);
        ret = blk_insert_bs(blk, bs, errp);
        if (ret < 0) {
            error_report_err(local_err);
            blk_unref(blk);
            return ret;
        }

        ret = blk_truncate(blk, new_size, PREALLOC_MODE_OFF, &local_err);
        ret = blk_truncate(blk, new_size, PREALLOC_MODE_OFF, errp);
        blk_unref(blk);
        if (ret < 0) {
            error_report_err(local_err);
            return ret;
        }
    }
@@ -4536,7 +4546,7 @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts,
    if (new_version < old_version) {
        helper_cb_info.current_operation = QCOW2_DOWNGRADING;
        ret = qcow2_downgrade(bs, new_version, &qcow2_amend_helper_cb,
                              &helper_cb_info);
                              &helper_cb_info, errp);
        if (ret < 0) {
            return ret;
        }
@@ -4559,7 +4569,7 @@ void qcow2_signal_corruption(BlockDriverState *bs, bool fatal, int64_t offset,
    char *message;
    va_list ap;

    fatal = fatal && !bs->read_only;
    fatal = fatal && bdrv_is_writable(bs);

    if (s->signaled_corruption &&
        (!fatal || (s->incompatible_features & QCOW2_INCOMPAT_CORRUPT)))
Loading