Commit ce59ecc4 authored by Peter Maydell's avatar Peter Maydell
Browse files

Merge remote-tracking branch 'remotes/kevin/tags/for-upstream' into staging



Block layer patches:

- Make truncate operations asynchronous (so that preallocation in
  blockdev-create doesn't block the main loop any more)
- usb-storage: Add rerror/werror properties
- nvme: Add num_queues property
- qemu-img convert: Copy offloading fixes (including data corruption fix)
- qcow2: Fix cluster leak on temporary write error
- Use byte-based functions instead of bdrv_co_readv/writev()
- Various small fixes and cleanups

# gpg: Signature made Fri 29 Jun 2018 15:08:34 BST
# gpg:                using RSA key 7F09B272C88F2FD6
# gpg: Good signature from "Kevin Wolf <kwolf@redhat.com>"
# Primary key fingerprint: DC3D EB15 9A9A F95D 3D74  56FE 7F09 B272 C88F 2FD6

* remotes/kevin/tags/for-upstream: (29 commits)
  block: Remove unused sector-based vectored I/O
  vhdx: Switch to byte-based calls
  replication: Switch to byte-based calls
  qcow: Switch to a byte-based driver
  qcow: Switch qcow_co_writev to byte-based calls
  qcow: Switch qcow_co_readv to byte-based calls
  qcow: Switch get_cluster_offset to be byte-based
  parallels: Switch to byte-based calls
  file-posix: Fix EINTR handling
  iscsi: Don't blindly use designator length in response for memcpy
  qcow2: Fix src_offset in copy offloading
  file-posix: Implement co versions of discard/flush
  qemu-iotests: Test qcow2 not leaking clusters on write error
  qcow2: Free allocated clusters on write error
  qemu-iotests: Update 026.out.nocache reference output
  block/crypto: Simplify block_crypto_{open,create}_opts_init()
  block: Move request tracking to children in copy offloading
  qcow2: Remove dead check on !ret
  file-posix: Make .bdrv_co_truncate asynchronous
  block: Use tracked request for truncate
  ...

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents b2866c29 583c99d3
Loading
Loading
Loading
Loading
+1 −63
Original line number Diff line number Diff line
@@ -725,7 +725,7 @@ static int find_image_format(BlockBackend *file, const char *filename,
 * Set the current 'total_sectors' value
 * Return 0 on success, -errno on error.
 */
static int refresh_total_sectors(BlockDriverState *bs, int64_t hint)
int refresh_total_sectors(BlockDriverState *bs, int64_t hint)
{
    BlockDriver *drv = bs->drv;

@@ -2226,16 +2226,6 @@ static void bdrv_parent_cb_change_media(BlockDriverState *bs, bool load)
    }
}

static void bdrv_parent_cb_resize(BlockDriverState *bs)
{
    BdrvChild *c;
    QLIST_FOREACH(c, &bs->parents, next_parent) {
        if (c->role->resize) {
            c->role->resize(c);
        }
    }
}

/*
 * Sets the backing file link of a BDS. A new reference is created; callers
 * which don't need their own reference any more must call bdrv_unref().
@@ -3785,58 +3775,6 @@ exit:
    return ret;
}

/**
 * Truncate file to 'offset' bytes (needed only for file protocols)
 */
int bdrv_truncate(BdrvChild *child, int64_t offset, PreallocMode prealloc,
                  Error **errp)
{
    BlockDriverState *bs = child->bs;
    BlockDriver *drv = bs->drv;
    int ret;

    assert(child->perm & BLK_PERM_RESIZE);

    /* if bs->drv == NULL, bs is closed, so there's nothing to do here */
    if (!drv) {
        error_setg(errp, "No medium inserted");
        return -ENOMEDIUM;
    }
    if (offset < 0) {
        error_setg(errp, "Image size cannot be negative");
        return -EINVAL;
    }

    if (!drv->bdrv_truncate) {
        if (bs->file && drv->is_filter) {
            return bdrv_truncate(bs->file, offset, prealloc, errp);
        }
        error_setg(errp, "Image format driver does not support resize");
        return -ENOTSUP;
    }
    if (bs->read_only) {
        error_setg(errp, "Image is read-only");
        return -EACCES;
    }

    assert(!(bs->open_flags & BDRV_O_INACTIVE));

    ret = drv->bdrv_truncate(bs, offset, prealloc, errp);
    if (ret < 0) {
        return ret;
    }
    ret = refresh_total_sectors(bs, offset >> BDRV_SECTOR_BITS);
    if (ret < 0) {
        error_setg_errno(errp, -ret, "Could not refresh total sector count");
    } else {
        offset = bs->total_sectors * BDRV_SECTOR_SIZE;
    }
    bdrv_dirty_bitmap_truncate(bs, offset);
    bdrv_parent_cb_resize(bs);
    atomic_inc(&bs->write_gen);
    return ret;
}

/**
 * Length of a allocated file in bytes. Sparse files are counted by actual
 * allocated space. Return < 0 if error or unknown.
+4 −4
Original line number Diff line number Diff line
@@ -80,10 +80,10 @@ static int64_t cor_getlength(BlockDriverState *bs)
}


static int cor_truncate(BlockDriverState *bs, int64_t offset,
static int coroutine_fn cor_co_truncate(BlockDriverState *bs, int64_t offset,
                                        PreallocMode prealloc, Error **errp)
{
    return bdrv_truncate(bs->file, offset, prealloc, errp);
    return bdrv_co_truncate(bs->file, offset, prealloc, errp);
}


@@ -147,7 +147,7 @@ BlockDriver bdrv_copy_on_read = {
    .bdrv_child_perm                    = cor_child_perm,

    .bdrv_getlength                     = cor_getlength,
    .bdrv_truncate                      = cor_truncate,
    .bdrv_co_truncate                   = cor_co_truncate,

    .bdrv_co_preadv                     = cor_co_preadv,
    .bdrv_co_pwritev                    = cor_co_pwritev,
+21 −91
Original line number Diff line number Diff line
@@ -148,108 +148,36 @@ static QemuOptsList block_crypto_create_opts_luks = {


QCryptoBlockOpenOptions *
block_crypto_open_opts_init(QCryptoBlockFormat format,
                            QDict *opts,
                            Error **errp)
block_crypto_open_opts_init(QDict *opts, Error **errp)
{
    Visitor *v;
    QCryptoBlockOpenOptions *ret = NULL;
    Error *local_err = NULL;

    ret = g_new0(QCryptoBlockOpenOptions, 1);
    ret->format = format;

    v = qobject_input_visitor_new_flat_confused(opts, &local_err);
    if (local_err) {
        goto out;
    }

    visit_start_struct(v, NULL, NULL, 0, &local_err);
    if (local_err) {
        goto out;
    }
    QCryptoBlockOpenOptions *ret;

    switch (format) {
    case Q_CRYPTO_BLOCK_FORMAT_LUKS:
        visit_type_QCryptoBlockOptionsLUKS_members(
            v, &ret->u.luks, &local_err);
        break;

    case Q_CRYPTO_BLOCK_FORMAT_QCOW:
        visit_type_QCryptoBlockOptionsQCow_members(
            v, &ret->u.qcow, &local_err);
        break;

    default:
        error_setg(&local_err, "Unsupported block format %d", format);
        break;
    }
    if (!local_err) {
        visit_check_struct(v, &local_err);
    v = qobject_input_visitor_new_flat_confused(opts, errp);
    if (!v) {
        return NULL;
    }

    visit_end_struct(v, NULL);
    visit_type_QCryptoBlockOpenOptions(v, NULL, &ret, errp);

 out:
    if (local_err) {
        error_propagate(errp, local_err);
        qapi_free_QCryptoBlockOpenOptions(ret);
        ret = NULL;
    }
    visit_free(v);
    return ret;
}


QCryptoBlockCreateOptions *
block_crypto_create_opts_init(QCryptoBlockFormat format,
                              QDict *opts,
                              Error **errp)
block_crypto_create_opts_init(QDict *opts, Error **errp)
{
    Visitor *v;
    QCryptoBlockCreateOptions *ret = NULL;
    Error *local_err = NULL;

    ret = g_new0(QCryptoBlockCreateOptions, 1);
    ret->format = format;

    v = qobject_input_visitor_new_flat_confused(opts, &local_err);
    if (local_err) {
        goto out;
    }

    visit_start_struct(v, NULL, NULL, 0, &local_err);
    if (local_err) {
        goto out;
    }
    QCryptoBlockCreateOptions *ret;

    switch (format) {
    case Q_CRYPTO_BLOCK_FORMAT_LUKS:
        visit_type_QCryptoBlockCreateOptionsLUKS_members(
            v, &ret->u.luks, &local_err);
        break;

    case Q_CRYPTO_BLOCK_FORMAT_QCOW:
        visit_type_QCryptoBlockOptionsQCow_members(
            v, &ret->u.qcow, &local_err);
        break;

    default:
        error_setg(&local_err, "Unsupported block format %d", format);
        break;
    }
    if (!local_err) {
        visit_check_struct(v, &local_err);
    v = qobject_input_visitor_new_flat_confused(opts, errp);
    if (!v) {
        return NULL;
    }

    visit_end_struct(v, NULL);
    visit_type_QCryptoBlockCreateOptions(v, NULL, &ret, errp);

 out:
    if (local_err) {
        error_propagate(errp, local_err);
        qapi_free_QCryptoBlockCreateOptions(ret);
        ret = NULL;
    }
    visit_free(v);
    return ret;
}
@@ -287,8 +215,9 @@ static int block_crypto_open_generic(QCryptoBlockFormat format,
    }

    cryptoopts = qemu_opts_to_qdict(opts, NULL);
    qdict_put_str(cryptoopts, "format", QCryptoBlockFormat_str(format));

    open_opts = block_crypto_open_opts_init(format, cryptoopts, errp);
    open_opts = block_crypto_open_opts_init(cryptoopts, errp);
    if (!open_opts) {
        goto cleanup;
    }
@@ -357,7 +286,8 @@ static int block_crypto_co_create_generic(BlockDriverState *bs,
    return ret;
}

static int block_crypto_truncate(BlockDriverState *bs, int64_t offset,
static int coroutine_fn
block_crypto_co_truncate(BlockDriverState *bs, int64_t offset,
                         PreallocMode prealloc, Error **errp)
{
    BlockCrypto *crypto = bs->opaque;
@@ -371,7 +301,7 @@ static int block_crypto_truncate(BlockDriverState *bs, int64_t offset,

    offset += payload_offset;

    return bdrv_truncate(bs->file, offset, prealloc, errp);
    return bdrv_co_truncate(bs->file, offset, prealloc, errp);
}

static void block_crypto_close(BlockDriverState *bs)
@@ -611,8 +541,8 @@ static int coroutine_fn block_crypto_co_create_opts_luks(const char *filename,
                                             &block_crypto_create_opts_luks,
                                             true);

    create_opts = block_crypto_create_opts_init(Q_CRYPTO_BLOCK_FORMAT_LUKS,
                                                cryptoopts, errp);
    qdict_put_str(cryptoopts, "format", "luks");
    create_opts = block_crypto_create_opts_init(cryptoopts, errp);
    if (!create_opts) {
        ret = -EINVAL;
        goto fail;
@@ -700,7 +630,7 @@ BlockDriver bdrv_crypto_luks = {
    .bdrv_child_perm    = bdrv_format_default_perms,
    .bdrv_co_create     = block_crypto_co_create_luks,
    .bdrv_co_create_opts = block_crypto_co_create_opts_luks,
    .bdrv_truncate      = block_crypto_truncate,
    .bdrv_co_truncate   = block_crypto_co_truncate,
    .create_opts        = &block_crypto_create_opts_luks,

    .bdrv_reopen_prepare = block_crypto_reopen_prepare,
+2 −6
Original line number Diff line number Diff line
@@ -89,13 +89,9 @@
    }

QCryptoBlockCreateOptions *
block_crypto_create_opts_init(QCryptoBlockFormat format,
                              QDict *opts,
                              Error **errp);
block_crypto_create_opts_init(QDict *opts, Error **errp);

QCryptoBlockOpenOptions *
block_crypto_open_opts_init(QCryptoBlockFormat format,
                            QDict *opts,
                            Error **errp);
block_crypto_open_opts_init(QDict *opts, Error **errp);

#endif /* BLOCK_CRYPTO_H__ */
+190 −177
Original line number Diff line number Diff line
@@ -188,8 +188,16 @@ typedef struct RawPosixAIOData {
#define aio_ioctl_cmd   aio_nbytes /* for QEMU_AIO_IOCTL */
    off_t aio_offset;
    int aio_type;
    union {
        struct {
            int aio_fd2;
            off_t aio_offset2;
        };
        struct {
            PreallocMode prealloc;
            Error **errp;
        };
    };
} RawPosixAIOData;

#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
@@ -1480,20 +1488,21 @@ static ssize_t handle_aiocb_copy_range(RawPosixAIOData *aiocb)
        ssize_t ret = copy_file_range(aiocb->aio_fildes, &in_off,
                                      aiocb->aio_fd2, &out_off,
                                      bytes, 0);
        if (ret == -EINTR) {
            continue;
        if (ret == 0) {
            /* No progress (e.g. when beyond EOF), let the caller fall back to
             * buffer I/O. */
            return -ENOSPC;
        }
        if (ret < 0) {
            if (errno == ENOSYS) {
            switch (errno) {
            case ENOSYS:
                return -ENOTSUP;
            } else {
            case EINTR:
                continue;
            default:
                return -errno;
            }
        }
        if (!ret) {
            /* No progress (e.g. when beyond EOF), fall back to buffer I/O. */
            return -ENOTSUP;
        }
        bytes -= ret;
    }
    return 0;
@@ -1539,6 +1548,122 @@ static ssize_t handle_aiocb_discard(RawPosixAIOData *aiocb)
    return ret;
}

static int handle_aiocb_truncate(RawPosixAIOData *aiocb)
{
    int result = 0;
    int64_t current_length = 0;
    char *buf = NULL;
    struct stat st;
    int fd = aiocb->aio_fildes;
    int64_t offset = aiocb->aio_offset;
    Error **errp = aiocb->errp;

    if (fstat(fd, &st) < 0) {
        result = -errno;
        error_setg_errno(errp, -result, "Could not stat file");
        return result;
    }

    current_length = st.st_size;
    if (current_length > offset && aiocb->prealloc != 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 if a
         * block is allocated before allocating it, so don't do that here.
         */
        if (offset != current_length) {
            result = -posix_fallocate(fd, current_length,
                                      offset - current_length);
            if (result != 0) {
                /* posix_fallocate() doesn't set errno. */
                error_setg_errno(errp, -result,
                                 "Could not preallocate new data");
            }
        } else {
            result = 0;
        }
        goto out;
#endif
    case PREALLOC_MODE_FULL:
    {
        int64_t num = 0, left = 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) != 0) {
            result = -errno;
            error_setg_errno(errp, -result, "Could not resize file");
            goto out;
        }

        buf = g_malloc0(65536);

        seek_result = lseek(fd, current_length, SEEK_SET);
        if (seek_result < 0) {
            result = -errno;
            error_setg_errno(errp, -result,
                             "Failed to seek to the old end of file");
            goto out;
        }

        while (left > 0) {
            num = MIN(left, 65536);
            result = write(fd, buf, num);
            if (result < 0) {
                result = -errno;
                error_setg_errno(errp, -result,
                                 "Could not write zeros for preallocation");
                goto out;
            }
            left -= result;
        }
        if (result >= 0) {
            result = fsync(fd);
            if (result < 0) {
                result = -errno;
                error_setg_errno(errp, -result,
                                 "Could not flush file to disk");
                goto out;
            }
        }
        goto out;
    }
    case PREALLOC_MODE_OFF:
        if (ftruncate(fd, offset) != 0) {
            result = -errno;
            error_setg_errno(errp, -result, "Could not resize file");
        }
        return result;
    default:
        result = -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 = arg;
@@ -1582,6 +1707,9 @@ static int aio_worker(void *arg)
    case QEMU_AIO_COPY_RANGE:
        ret = handle_aiocb_copy_range(aiocb);
        break;
    case QEMU_AIO_TRUNCATE:
        ret = handle_aiocb_truncate(aiocb);
        break;
    default:
        fprintf(stderr, "invalid aio request (0x%x)\n", aiocb->aio_type);
        ret = -EINVAL;
@@ -1627,31 +1755,6 @@ static inline int paio_submit_co(BlockDriverState *bs, int fd,
    return paio_submit_co_full(bs, fd, offset, -1, 0, qiov, bytes, type);
}

static BlockAIOCB *paio_submit(BlockDriverState *bs, int fd,
        int64_t offset, QEMUIOVector *qiov, int bytes,
        BlockCompletionFunc *cb, void *opaque, int type)
{
    RawPosixAIOData *acb = g_new(RawPosixAIOData, 1);
    ThreadPool *pool;

    acb->bs = bs;
    acb->aio_type = type;
    acb->aio_fildes = fd;

    acb->aio_nbytes = bytes;
    acb->aio_offset = offset;

    if (qiov) {
        acb->aio_iov = qiov->iov;
        acb->aio_niov = qiov->niov;
        assert(qiov->size == acb->aio_nbytes);
    }

    trace_paio_submit(acb, opaque, offset, bytes, type);
    pool = aio_get_thread_pool(bdrv_get_aio_context(bs));
    return thread_pool_submit_aio(pool, aio_worker, acb, cb, opaque);
}

static int coroutine_fn raw_co_prw(BlockDriverState *bs, uint64_t offset,
                                   uint64_t bytes, QEMUIOVector *qiov, int type)
{
@@ -1718,15 +1821,17 @@ static void raw_aio_unplug(BlockDriverState *bs)
#endif
}

static BlockAIOCB *raw_aio_flush(BlockDriverState *bs,
        BlockCompletionFunc *cb, void *opaque)
static int raw_co_flush_to_disk(BlockDriverState *bs)
{
    BDRVRawState *s = bs->opaque;
    int ret;

    if (fd_open(bs) < 0)
        return NULL;
    ret = fd_open(bs);
    if (ret < 0) {
        return ret;
    }

    return paio_submit(bs, s->fd, 0, NULL, 0, cb, opaque, QEMU_AIO_FLUSH);
    return paio_submit_co(bs, s->fd, 0, NULL, 0, QEMU_AIO_FLUSH);
}

static void raw_aio_attach_aio_context(BlockDriverState *bs,
@@ -1765,120 +1870,28 @@ static void raw_close(BlockDriverState *bs)
 *
 * Returns: 0 on success, -errno on failure.
 */
static int raw_regular_truncate(int fd, int64_t offset, PreallocMode prealloc,
                                Error **errp)
{
    int result = 0;
    int64_t current_length = 0;
    char *buf = NULL;
    struct stat st;

    if (fstat(fd, &st) < 0) {
        result = -errno;
        error_setg_errno(errp, -result, "Could not stat file");
        return result;
    }

    current_length = st.st_size;
    if (current_length > offset && prealloc != 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 if a
         * block is allocated before allocating it, so don't do that here.
         */
        if (offset != current_length) {
            result = -posix_fallocate(fd, current_length, offset - current_length);
            if (result != 0) {
                /* posix_fallocate() doesn't set errno. */
                error_setg_errno(errp, -result,
                                 "Could not preallocate new data");
            }
        } else {
            result = 0;
        }
        goto out;
#endif
    case PREALLOC_MODE_FULL:
static int coroutine_fn
raw_regular_truncate(BlockDriverState *bs, int fd, int64_t offset,
                     PreallocMode prealloc, Error **errp)
{
        int64_t num = 0, left = 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) != 0) {
            result = -errno;
            error_setg_errno(errp, -result, "Could not resize file");
            goto out;
        }

        buf = g_malloc0(65536);

        seek_result = lseek(fd, current_length, SEEK_SET);
        if (seek_result < 0) {
            result = -errno;
            error_setg_errno(errp, -result,
                             "Failed to seek to the old end of file");
            goto out;
        }

        while (left > 0) {
            num = MIN(left, 65536);
            result = write(fd, buf, num);
            if (result < 0) {
                result = -errno;
                error_setg_errno(errp, -result,
                                 "Could not write zeros for preallocation");
                goto out;
            }
            left -= result;
        }
        if (result >= 0) {
            result = fsync(fd);
            if (result < 0) {
                result = -errno;
                error_setg_errno(errp, -result,
                                 "Could not flush file to disk");
                goto out;
            }
        }
        goto out;
    }
    case PREALLOC_MODE_OFF:
        if (ftruncate(fd, offset) != 0) {
            result = -errno;
            error_setg_errno(errp, -result, "Could not resize file");
        }
        return result;
    default:
        result = -ENOTSUP;
        error_setg(errp, "Unsupported preallocation mode: %s",
                   PreallocMode_str(prealloc));
        return result;
    }
    RawPosixAIOData *acb = g_new(RawPosixAIOData, 1);
    ThreadPool *pool;

out:
    if (result < 0) {
        if (ftruncate(fd, current_length) < 0) {
            error_report("Failed to restore old file length: %s",
                         strerror(errno));
        }
    }
    *acb = (RawPosixAIOData) {
        .bs             = bs,
        .aio_fildes     = fd,
        .aio_type       = QEMU_AIO_TRUNCATE,
        .aio_offset     = offset,
        .prealloc       = prealloc,
        .errp           = errp,
    };

    g_free(buf);
    return result;
    /* @bs can be NULL, bdrv_get_aio_context() returns the main context then */
    pool = aio_get_thread_pool(bdrv_get_aio_context(bs));
    return thread_pool_submit_co(pool, aio_worker, acb);
}

static int raw_truncate(BlockDriverState *bs, int64_t offset,
static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset,
                                        PreallocMode prealloc, Error **errp)
{
    BDRVRawState *s = bs->opaque;
@@ -1892,7 +1905,7 @@ static int raw_truncate(BlockDriverState *bs, int64_t offset,
    }

    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);
    }

    if (prealloc != PREALLOC_MODE_OFF) {
@@ -2094,7 +2107,8 @@ static int64_t raw_get_allocated_file_size(BlockDriverState *bs)
    return (int64_t)st.st_blocks * 512;
}

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;
@@ -2146,7 +2160,7 @@ static int raw_co_create(BlockdevCreateOptions *options, Error **errp)
    }

    /* Clear the file by truncating it to 0 */
    result = raw_regular_truncate(fd, 0, PREALLOC_MODE_OFF, errp);
    result = raw_regular_truncate(NULL, fd, 0, PREALLOC_MODE_OFF, errp);
    if (result < 0) {
        goto out_close;
    }
@@ -2168,8 +2182,8 @@ static int raw_co_create(BlockdevCreateOptions *options, Error **errp)

    /* Resize and potentially preallocate the file to the desired
     * final size */
    result = raw_regular_truncate(fd, file_opts->size, file_opts->preallocation,
                                  errp);
    result = raw_regular_truncate(NULL, fd, file_opts->size,
                                  file_opts->preallocation, errp);
    if (result < 0) {
        goto out_close;
    }
@@ -2490,14 +2504,12 @@ static void coroutine_fn raw_co_invalidate_cache(BlockDriverState *bs,
#endif /* !__linux__ */
}

static coroutine_fn BlockAIOCB *raw_aio_pdiscard(BlockDriverState *bs,
    int64_t offset, int bytes,
    BlockCompletionFunc *cb, void *opaque)
static coroutine_fn int
raw_co_pdiscard(BlockDriverState *bs, int64_t offset, int bytes)
{
    BDRVRawState *s = bs->opaque;

    return paio_submit(bs, s->fd, offset, NULL, bytes,
                       cb, opaque, QEMU_AIO_DISCARD);
    return paio_submit_co(bs, s->fd, offset, NULL, bytes, QEMU_AIO_DISCARD);
}

static int coroutine_fn raw_co_pwrite_zeroes(
@@ -2616,8 +2628,8 @@ BlockDriver bdrv_file = {

    .bdrv_co_preadv         = raw_co_preadv,
    .bdrv_co_pwritev        = raw_co_pwritev,
    .bdrv_aio_flush = raw_aio_flush,
    .bdrv_aio_pdiscard = raw_aio_pdiscard,
    .bdrv_co_flush_to_disk  = raw_co_flush_to_disk,
    .bdrv_co_pdiscard       = raw_co_pdiscard,
    .bdrv_co_copy_range_from = raw_co_copy_range_from,
    .bdrv_co_copy_range_to  = raw_co_copy_range_to,
    .bdrv_refresh_limits = raw_refresh_limits,
@@ -2625,7 +2637,7 @@ BlockDriver bdrv_file = {
    .bdrv_io_unplug = raw_aio_unplug,
    .bdrv_attach_aio_context = raw_aio_attach_aio_context,

    .bdrv_truncate = raw_truncate,
    .bdrv_co_truncate = raw_co_truncate,
    .bdrv_getlength = raw_getlength,
    .bdrv_get_info = raw_get_info,
    .bdrv_get_allocated_file_size
@@ -2983,17 +2995,18 @@ static int fd_open(BlockDriverState *bs)
    return -EIO;
}

static coroutine_fn BlockAIOCB *hdev_aio_pdiscard(BlockDriverState *bs,
    int64_t offset, int bytes,
    BlockCompletionFunc *cb, void *opaque)
static coroutine_fn int
hdev_co_pdiscard(BlockDriverState *bs, int64_t offset, int bytes)
{
    BDRVRawState *s = bs->opaque;
    int ret;

    if (fd_open(bs) < 0) {
        return NULL;
    ret = fd_open(bs);
    if (ret < 0) {
        return ret;
    }
    return paio_submit(bs, s->fd, offset, NULL, bytes,
                       cb, opaque, QEMU_AIO_DISCARD|QEMU_AIO_BLKDEV);
    return paio_submit_co(bs, s->fd, offset, NULL, bytes,
                          QEMU_AIO_DISCARD | QEMU_AIO_BLKDEV);
}

static coroutine_fn int hdev_co_pwrite_zeroes(BlockDriverState *bs,
@@ -3097,15 +3110,15 @@ static BlockDriver bdrv_host_device = {

    .bdrv_co_preadv         = raw_co_preadv,
    .bdrv_co_pwritev        = raw_co_pwritev,
    .bdrv_aio_flush	= raw_aio_flush,
    .bdrv_aio_pdiscard   = hdev_aio_pdiscard,
    .bdrv_co_flush_to_disk  = raw_co_flush_to_disk,
    .bdrv_co_pdiscard       = hdev_co_pdiscard,
    .bdrv_co_copy_range_from = raw_co_copy_range_from,
    .bdrv_co_copy_range_to  = raw_co_copy_range_to,
    .bdrv_refresh_limits = raw_refresh_limits,
    .bdrv_io_plug = raw_aio_plug,
    .bdrv_io_unplug = raw_aio_unplug,

    .bdrv_truncate      = raw_truncate,
    .bdrv_co_truncate       = raw_co_truncate,
    .bdrv_getlength	= raw_getlength,
    .bdrv_get_info = raw_get_info,
    .bdrv_get_allocated_file_size
@@ -3222,12 +3235,12 @@ static BlockDriver bdrv_host_cdrom = {

    .bdrv_co_preadv         = raw_co_preadv,
    .bdrv_co_pwritev        = raw_co_pwritev,
    .bdrv_aio_flush	= raw_aio_flush,
    .bdrv_co_flush_to_disk  = raw_co_flush_to_disk,
    .bdrv_refresh_limits = raw_refresh_limits,
    .bdrv_io_plug = raw_aio_plug,
    .bdrv_io_unplug = raw_aio_unplug,

    .bdrv_truncate      = raw_truncate,
    .bdrv_co_truncate    = raw_co_truncate,
    .bdrv_getlength      = raw_getlength,
    .has_variable_length = true,
    .bdrv_get_allocated_file_size
@@ -3352,12 +3365,12 @@ static BlockDriver bdrv_host_cdrom = {

    .bdrv_co_preadv         = raw_co_preadv,
    .bdrv_co_pwritev        = raw_co_pwritev,
    .bdrv_aio_flush	= raw_aio_flush,
    .bdrv_co_flush_to_disk  = raw_co_flush_to_disk,
    .bdrv_refresh_limits = raw_refresh_limits,
    .bdrv_io_plug = raw_aio_plug,
    .bdrv_io_unplug = raw_aio_unplug,

    .bdrv_truncate      = raw_truncate,
    .bdrv_co_truncate    = raw_co_truncate,
    .bdrv_getlength      = raw_getlength,
    .has_variable_length = true,
    .bdrv_get_allocated_file_size
Loading