mirror of
https://github.com/qemu/qemu.git
synced 2024-12-03 16:53:53 +08:00
Block patches for the block queue
-----BEGIN PGP SIGNATURE----- iQFGBAABCAAwFiEEkb62CjDbPohX0Rgp9AfbAGHVz0AFAlkDjwgSHG1yZWl0ekBy ZWRoYXQuY29tAAoJEPQH2wBh1c9AwQ0H/1D/MyC4geQSRtV0KMl+I3DihxxYdMcl hQh9JOQlYK0/bSKkhKyzUhSx7dAQF1RoX7CPprvKT5wCrrAWN7RONVaRPnOjoAuM FAn9B0QBCxfQ9MIfDtpU1/5+JVv67EmMTmaVwTLIf6PhwYVFnokQJex29WiQqQI1 GJUELIqSOoAqeA0W3qtQs5xlGCkHwv25YIUHQntEITDql34SXfH6rUeVJajmB8sX X8Pi6FtpQka14o6b1us9cs2UIN5Kb2tuY2MYMGQChPmOKuGh5+F9MNTgV2it4BnU w+AeNyOOk8niIaXVfJ+D99UlVnx+bQ6VxcZzMFI0ssp/Fgpa5aU+zxI= =tw2A -----END PGP SIGNATURE----- Merge remote-tracking branch 'mreitz/tags/pull-block-2017-04-28' into queue-block Block patches for the block queue # gpg: Signature made Fri Apr 28 20:50:48 2017 CEST # gpg: using RSA key 0xF407DB0061D5CF40 # gpg: Good signature from "Max Reitz <mreitz@redhat.com>" # Primary key fingerprint: 91BE B60A 30DB 3E88 57D1 1829 F407 DB00 61D5 CF40 * mreitz/tags/pull-block-2017-04-28: progress: Show current progress on SIGINFO iotests: fix exclusion option iotests: clarify help text qemu-img: use blk_co_pwrite_zeroes for zero sectors when compressed qemu-img: improve convert_iteration_sectors() block: assert no image modification under BDRV_O_INACTIVE block: fix obvious coding style mistakes in block_int.h qcow2: Allow discard of final unaligned cluster block: Add .bdrv_truncate() error messages block: Add errp to BD.bdrv_truncate() block: Add errp to b{lk,drv}_truncate() block/vhdx: Make vhdx_create() always set errp Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
commit
5fc0fe383f
18
block.c
18
block.c
@ -3307,7 +3307,7 @@ exit:
|
||||
/**
|
||||
* Truncate file to 'offset' bytes (needed only for file protocols)
|
||||
*/
|
||||
int bdrv_truncate(BdrvChild *child, int64_t offset)
|
||||
int bdrv_truncate(BdrvChild *child, int64_t offset, Error **errp)
|
||||
{
|
||||
BlockDriverState *bs = child->bs;
|
||||
BlockDriver *drv = bs->drv;
|
||||
@ -3315,14 +3315,22 @@ int bdrv_truncate(BdrvChild *child, int64_t offset)
|
||||
|
||||
assert(child->perm & BLK_PERM_RESIZE);
|
||||
|
||||
if (!drv)
|
||||
if (!drv) {
|
||||
error_setg(errp, "No medium inserted");
|
||||
return -ENOMEDIUM;
|
||||
if (!drv->bdrv_truncate)
|
||||
}
|
||||
if (!drv->bdrv_truncate) {
|
||||
error_setg(errp, "Image format driver does not support resize");
|
||||
return -ENOTSUP;
|
||||
if (bs->read_only)
|
||||
}
|
||||
if (bs->read_only) {
|
||||
error_setg(errp, "Image is read-only");
|
||||
return -EACCES;
|
||||
}
|
||||
|
||||
ret = drv->bdrv_truncate(bs, offset);
|
||||
assert(!(bs->open_flags & BDRV_O_INACTIVE));
|
||||
|
||||
ret = drv->bdrv_truncate(bs, offset, errp);
|
||||
if (ret == 0) {
|
||||
ret = refresh_total_sectors(bs, offset >> BDRV_SECTOR_BITS);
|
||||
bdrv_dirty_bitmap_truncate(bs);
|
||||
|
@ -659,9 +659,9 @@ static int64_t blkdebug_getlength(BlockDriverState *bs)
|
||||
return bdrv_getlength(bs->file->bs);
|
||||
}
|
||||
|
||||
static int blkdebug_truncate(BlockDriverState *bs, int64_t offset)
|
||||
static int blkdebug_truncate(BlockDriverState *bs, int64_t offset, Error **errp)
|
||||
{
|
||||
return bdrv_truncate(bs->file, offset);
|
||||
return bdrv_truncate(bs->file, offset, errp);
|
||||
}
|
||||
|
||||
static void blkdebug_refresh_filename(BlockDriverState *bs, QDict *options)
|
||||
|
@ -1746,13 +1746,14 @@ int blk_pwrite_compressed(BlockBackend *blk, int64_t offset, const void *buf,
|
||||
BDRV_REQ_WRITE_COMPRESSED);
|
||||
}
|
||||
|
||||
int blk_truncate(BlockBackend *blk, int64_t offset)
|
||||
int blk_truncate(BlockBackend *blk, int64_t offset, Error **errp)
|
||||
{
|
||||
if (!blk_is_available(blk)) {
|
||||
error_setg(errp, "No medium inserted");
|
||||
return -ENOMEDIUM;
|
||||
}
|
||||
|
||||
return bdrv_truncate(blk->root, offset);
|
||||
return bdrv_truncate(blk->root, offset, errp);
|
||||
}
|
||||
|
||||
static void blk_pdiscard_entry(void *opaque)
|
||||
|
@ -151,7 +151,7 @@ static void coroutine_fn commit_run(void *opaque)
|
||||
}
|
||||
|
||||
if (base_len < s->common.len) {
|
||||
ret = blk_truncate(s->base, s->common.len);
|
||||
ret = blk_truncate(s->base, s->common.len, NULL);
|
||||
if (ret) {
|
||||
goto out;
|
||||
}
|
||||
@ -511,8 +511,9 @@ int bdrv_commit(BlockDriverState *bs)
|
||||
* grow the backing file image if possible. If not possible,
|
||||
* we must return an error */
|
||||
if (length > backing_length) {
|
||||
ret = blk_truncate(backing, length);
|
||||
ret = blk_truncate(backing, length, &local_err);
|
||||
if (ret < 0) {
|
||||
error_report_err(local_err);
|
||||
goto ro_cleanup;
|
||||
}
|
||||
}
|
||||
|
@ -381,7 +381,8 @@ static int block_crypto_create_generic(QCryptoBlockFormat format,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int block_crypto_truncate(BlockDriverState *bs, int64_t offset)
|
||||
static int block_crypto_truncate(BlockDriverState *bs, int64_t offset,
|
||||
Error **errp)
|
||||
{
|
||||
BlockCrypto *crypto = bs->opaque;
|
||||
size_t payload_offset =
|
||||
@ -389,7 +390,7 @@ static int block_crypto_truncate(BlockDriverState *bs, int64_t offset)
|
||||
|
||||
offset += payload_offset;
|
||||
|
||||
return bdrv_truncate(bs->file, offset);
|
||||
return bdrv_truncate(bs->file, offset, errp);
|
||||
}
|
||||
|
||||
static void block_crypto_close(BlockDriverState *bs)
|
||||
|
@ -1407,24 +1407,31 @@ static void raw_close(BlockDriverState *bs)
|
||||
}
|
||||
}
|
||||
|
||||
static int raw_truncate(BlockDriverState *bs, int64_t offset)
|
||||
static int raw_truncate(BlockDriverState *bs, int64_t offset, Error **errp)
|
||||
{
|
||||
BDRVRawState *s = bs->opaque;
|
||||
struct stat st;
|
||||
int ret;
|
||||
|
||||
if (fstat(s->fd, &st)) {
|
||||
return -errno;
|
||||
ret = -errno;
|
||||
error_setg_errno(errp, -ret, "Failed to fstat() the file");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (S_ISREG(st.st_mode)) {
|
||||
if (ftruncate(s->fd, offset) < 0) {
|
||||
return -errno;
|
||||
ret = -errno;
|
||||
error_setg_errno(errp, -ret, "Failed to resize the file");
|
||||
return ret;
|
||||
}
|
||||
} else if (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode)) {
|
||||
if (offset > raw_getlength(bs)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
if (offset > raw_getlength(bs)) {
|
||||
error_setg(errp, "Cannot grow device files");
|
||||
return -EINVAL;
|
||||
}
|
||||
} else {
|
||||
error_setg(errp, "Resizing this file is not supported");
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
|
@ -460,7 +460,7 @@ static void raw_close(BlockDriverState *bs)
|
||||
}
|
||||
}
|
||||
|
||||
static int raw_truncate(BlockDriverState *bs, int64_t offset)
|
||||
static int raw_truncate(BlockDriverState *bs, int64_t offset, Error **errp)
|
||||
{
|
||||
BDRVRawState *s = bs->opaque;
|
||||
LONG low, high;
|
||||
@ -475,11 +475,11 @@ static int raw_truncate(BlockDriverState *bs, int64_t offset)
|
||||
*/
|
||||
dwPtrLow = SetFilePointer(s->hfile, low, &high, FILE_BEGIN);
|
||||
if (dwPtrLow == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR) {
|
||||
fprintf(stderr, "SetFilePointer error: %lu\n", GetLastError());
|
||||
error_setg_win32(errp, GetLastError(), "SetFilePointer error");
|
||||
return -EIO;
|
||||
}
|
||||
if (SetEndOfFile(s->hfile) == 0) {
|
||||
fprintf(stderr, "SetEndOfFile error: %lu\n", GetLastError());
|
||||
error_setg_win32(errp, GetLastError(), "SetEndOfFile error");
|
||||
return -EIO;
|
||||
}
|
||||
return 0;
|
||||
|
@ -1092,14 +1092,17 @@ static coroutine_fn int qemu_gluster_co_rw(BlockDriverState *bs,
|
||||
return acb.ret;
|
||||
}
|
||||
|
||||
static int qemu_gluster_truncate(BlockDriverState *bs, int64_t offset)
|
||||
static int qemu_gluster_truncate(BlockDriverState *bs, int64_t offset,
|
||||
Error **errp)
|
||||
{
|
||||
int ret;
|
||||
BDRVGlusterState *s = bs->opaque;
|
||||
|
||||
ret = glfs_ftruncate(s->fd, offset);
|
||||
if (ret < 0) {
|
||||
return -errno;
|
||||
ret = -errno;
|
||||
error_setg_errno(errp, -ret, "Failed to truncate file");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -2059,22 +2059,24 @@ static void iscsi_reopen_commit(BDRVReopenState *reopen_state)
|
||||
}
|
||||
}
|
||||
|
||||
static int iscsi_truncate(BlockDriverState *bs, int64_t offset)
|
||||
static int iscsi_truncate(BlockDriverState *bs, int64_t offset, Error **errp)
|
||||
{
|
||||
IscsiLun *iscsilun = bs->opaque;
|
||||
Error *local_err = NULL;
|
||||
|
||||
if (iscsilun->type != TYPE_DISK) {
|
||||
error_setg(errp, "Cannot resize non-disk iSCSI devices");
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
iscsi_readcapacity_sync(iscsilun, &local_err);
|
||||
if (local_err != NULL) {
|
||||
error_free(local_err);
|
||||
error_propagate(errp, local_err);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (offset > iscsi_getlength(bs)) {
|
||||
error_setg(errp, "Cannot grow iSCSI devices");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -724,7 +724,7 @@ static void coroutine_fn mirror_run(void *opaque)
|
||||
}
|
||||
|
||||
if (s->bdev_length > base_length) {
|
||||
ret = blk_truncate(s->target, s->bdev_length);
|
||||
ret = blk_truncate(s->target, s->bdev_length, NULL);
|
||||
if (ret < 0) {
|
||||
goto immediate_exit;
|
||||
}
|
||||
|
12
block/nfs.c
12
block/nfs.c
@ -764,10 +764,18 @@ static int64_t nfs_get_allocated_file_size(BlockDriverState *bs)
|
||||
return (task.ret < 0 ? task.ret : st.st_blocks * 512);
|
||||
}
|
||||
|
||||
static int nfs_file_truncate(BlockDriverState *bs, int64_t offset)
|
||||
static int nfs_file_truncate(BlockDriverState *bs, int64_t offset, Error **errp)
|
||||
{
|
||||
NFSClient *client = bs->opaque;
|
||||
return nfs_ftruncate(client->context, client->fh, offset);
|
||||
int ret;
|
||||
|
||||
ret = nfs_ftruncate(client->context, client->fh, offset);
|
||||
if (ret < 0) {
|
||||
error_setg_errno(errp, -ret, "Failed to truncate file");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Note that this will not re-establish a connection with the NFS server
|
||||
|
@ -223,7 +223,8 @@ static int64_t allocate_clusters(BlockDriverState *bs, int64_t sector_num,
|
||||
space << BDRV_SECTOR_BITS, 0);
|
||||
} else {
|
||||
ret = bdrv_truncate(bs->file,
|
||||
(s->data_end + space) << BDRV_SECTOR_BITS);
|
||||
(s->data_end + space) << BDRV_SECTOR_BITS,
|
||||
NULL);
|
||||
}
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
@ -456,8 +457,10 @@ static int parallels_check(BlockDriverState *bs, BdrvCheckResult *res,
|
||||
size - res->image_end_offset);
|
||||
res->leaks += count;
|
||||
if (fix & BDRV_FIX_LEAKS) {
|
||||
ret = bdrv_truncate(bs->file, res->image_end_offset);
|
||||
Error *local_err = NULL;
|
||||
ret = bdrv_truncate(bs->file, res->image_end_offset, &local_err);
|
||||
if (ret < 0) {
|
||||
error_report_err(local_err);
|
||||
res->check_errors++;
|
||||
return ret;
|
||||
}
|
||||
@ -504,7 +507,7 @@ static int parallels_create(const char *filename, QemuOpts *opts, Error **errp)
|
||||
|
||||
blk_set_allow_write_beyond_eof(file, true);
|
||||
|
||||
ret = blk_truncate(file, 0);
|
||||
ret = blk_truncate(file, 0, errp);
|
||||
if (ret < 0) {
|
||||
goto exit;
|
||||
}
|
||||
@ -696,7 +699,7 @@ static int parallels_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
}
|
||||
|
||||
if (!(flags & BDRV_O_RESIZE) || !bdrv_has_zero_init(bs->file->bs) ||
|
||||
bdrv_truncate(bs->file, bdrv_getlength(bs->file->bs)) != 0) {
|
||||
bdrv_truncate(bs->file, bdrv_getlength(bs->file->bs), NULL) != 0) {
|
||||
s->prealloc_mode = PRL_PREALLOC_MODE_FALLOCATE;
|
||||
}
|
||||
|
||||
@ -739,7 +742,7 @@ static void parallels_close(BlockDriverState *bs)
|
||||
}
|
||||
|
||||
if (bs->open_flags & BDRV_O_RDWR) {
|
||||
bdrv_truncate(bs->file, s->data_end << BDRV_SECTOR_BITS);
|
||||
bdrv_truncate(bs->file, s->data_end << BDRV_SECTOR_BITS, NULL);
|
||||
}
|
||||
|
||||
g_free(s->bat_dirty_bmap);
|
||||
|
@ -473,7 +473,7 @@ static uint64_t get_cluster_offset(BlockDriverState *bs,
|
||||
/* round to cluster size */
|
||||
cluster_offset = (cluster_offset + s->cluster_size - 1) &
|
||||
~(s->cluster_size - 1);
|
||||
bdrv_truncate(bs->file, cluster_offset + s->cluster_size);
|
||||
bdrv_truncate(bs->file, cluster_offset + s->cluster_size, NULL);
|
||||
/* if encrypted, we must initialize the cluster
|
||||
content which won't be written */
|
||||
if (bs->encrypted &&
|
||||
@ -833,7 +833,7 @@ static int qcow_create(const char *filename, QemuOpts *opts, Error **errp)
|
||||
|
||||
blk_set_allow_write_beyond_eof(qcow_blk, true);
|
||||
|
||||
ret = blk_truncate(qcow_blk, 0);
|
||||
ret = blk_truncate(qcow_blk, 0, errp);
|
||||
if (ret < 0) {
|
||||
goto exit;
|
||||
}
|
||||
@ -916,7 +916,7 @@ static int qcow_make_empty(BlockDriverState *bs)
|
||||
if (bdrv_pwrite_sync(bs->file, s->l1_table_offset, s->l1_table,
|
||||
l1_length) < 0)
|
||||
return -1;
|
||||
ret = bdrv_truncate(bs->file, s->l1_table_offset + l1_length);
|
||||
ret = bdrv_truncate(bs->file, s->l1_table_offset + l1_length, NULL);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
|
@ -1728,14 +1728,17 @@ static int check_refblocks(BlockDriverState *bs, BdrvCheckResult *res,
|
||||
|
||||
if (fix & BDRV_FIX_ERRORS) {
|
||||
int64_t new_nb_clusters;
|
||||
Error *local_err = NULL;
|
||||
|
||||
if (offset > INT64_MAX - s->cluster_size) {
|
||||
ret = -EINVAL;
|
||||
goto resize_fail;
|
||||
}
|
||||
|
||||
ret = bdrv_truncate(bs->file, offset + s->cluster_size);
|
||||
ret = bdrv_truncate(bs->file, offset + s->cluster_size,
|
||||
&local_err);
|
||||
if (ret < 0) {
|
||||
error_report_err(local_err);
|
||||
goto resize_fail;
|
||||
}
|
||||
size = bdrv_getlength(bs->file->bs);
|
||||
|
@ -2294,9 +2294,9 @@ static int qcow2_create2(const char *filename, int64_t total_size,
|
||||
}
|
||||
|
||||
/* Okay, now that we have a valid image, let's give it the right size */
|
||||
ret = blk_truncate(blk, total_size);
|
||||
ret = blk_truncate(blk, total_size, errp);
|
||||
if (ret < 0) {
|
||||
error_setg_errno(errp, -ret, "Could not resize image");
|
||||
error_prepend(errp, "Could not resize image: ");
|
||||
goto out;
|
||||
}
|
||||
|
||||
@ -2515,7 +2515,12 @@ static coroutine_fn int qcow2_co_pdiscard(BlockDriverState *bs,
|
||||
|
||||
if (!QEMU_IS_ALIGNED(offset | count, s->cluster_size)) {
|
||||
assert(count < s->cluster_size);
|
||||
return -ENOTSUP;
|
||||
/* Ignore partial clusters, except for the special case of the
|
||||
* complete partial cluster at the end of an unaligned file */
|
||||
if (!QEMU_IS_ALIGNED(offset, s->cluster_size) ||
|
||||
offset + count != bs->total_sectors * BDRV_SECTOR_SIZE) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
}
|
||||
|
||||
qemu_co_mutex_lock(&s->lock);
|
||||
@ -2525,32 +2530,33 @@ static coroutine_fn int qcow2_co_pdiscard(BlockDriverState *bs,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int qcow2_truncate(BlockDriverState *bs, int64_t offset)
|
||||
static int qcow2_truncate(BlockDriverState *bs, int64_t offset, Error **errp)
|
||||
{
|
||||
BDRVQcow2State *s = bs->opaque;
|
||||
int64_t new_l1_size;
|
||||
int ret;
|
||||
|
||||
if (offset & 511) {
|
||||
error_report("The new size must be a multiple of 512");
|
||||
error_setg(errp, "The new size must be a multiple of 512");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* cannot proceed if image has snapshots */
|
||||
if (s->nb_snapshots) {
|
||||
error_report("Can't resize an image which has snapshots");
|
||||
error_setg(errp, "Can't resize an image which has snapshots");
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
/* shrinking is currently not supported */
|
||||
if (offset < bs->total_sectors * 512) {
|
||||
error_report("qcow2 doesn't support shrinking images yet");
|
||||
error_setg(errp, "qcow2 doesn't support shrinking images yet");
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
new_l1_size = size_to_l1(s, offset);
|
||||
ret = qcow2_grow_l1_table(bs, new_l1_size, true);
|
||||
if (ret < 0) {
|
||||
error_setg_errno(errp, -ret, "Failed to grow the L1 table");
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -2559,6 +2565,7 @@ static int qcow2_truncate(BlockDriverState *bs, int64_t offset)
|
||||
ret = bdrv_pwrite_sync(bs->file, offsetof(QCowHeader, size),
|
||||
&offset, sizeof(uint64_t));
|
||||
if (ret < 0) {
|
||||
error_setg_errno(errp, -ret, "Failed to update the image size");
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -2584,7 +2591,7 @@ qcow2_co_pwritev_compressed(BlockDriverState *bs, uint64_t offset,
|
||||
/* align end of file to a sector boundary to ease reading with
|
||||
sector based I/Os */
|
||||
cluster_offset = bdrv_getlength(bs->file->bs);
|
||||
return bdrv_truncate(bs->file, cluster_offset);
|
||||
return bdrv_truncate(bs->file, cluster_offset, NULL);
|
||||
}
|
||||
|
||||
buf = qemu_blockalign(bs, s->cluster_size);
|
||||
@ -2674,6 +2681,7 @@ fail:
|
||||
static int make_completely_empty(BlockDriverState *bs)
|
||||
{
|
||||
BDRVQcow2State *s = bs->opaque;
|
||||
Error *local_err = NULL;
|
||||
int ret, l1_clusters;
|
||||
int64_t offset;
|
||||
uint64_t *new_reftable = NULL;
|
||||
@ -2798,8 +2806,10 @@ static int make_completely_empty(BlockDriverState *bs)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ret = bdrv_truncate(bs->file, (3 + l1_clusters) * s->cluster_size);
|
||||
ret = bdrv_truncate(bs->file, (3 + l1_clusters) * s->cluster_size,
|
||||
&local_err);
|
||||
if (ret < 0) {
|
||||
error_report_err(local_err);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@ -3273,9 +3283,10 @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts,
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = blk_truncate(blk, new_size);
|
||||
ret = blk_truncate(blk, new_size, &local_err);
|
||||
blk_unref(blk);
|
||||
if (ret < 0) {
|
||||
error_report_err(local_err);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
@ -635,7 +635,7 @@ static int qed_create(const char *filename, uint32_t cluster_size,
|
||||
blk_set_allow_write_beyond_eof(blk, true);
|
||||
|
||||
/* File must start empty and grow, check truncate is supported */
|
||||
ret = blk_truncate(blk, 0);
|
||||
ret = blk_truncate(blk, 0, errp);
|
||||
if (ret < 0) {
|
||||
goto out;
|
||||
}
|
||||
@ -1518,7 +1518,7 @@ static int coroutine_fn bdrv_qed_co_pwrite_zeroes(BlockDriverState *bs,
|
||||
return cb.ret;
|
||||
}
|
||||
|
||||
static int bdrv_qed_truncate(BlockDriverState *bs, int64_t offset)
|
||||
static int bdrv_qed_truncate(BlockDriverState *bs, int64_t offset, Error **errp)
|
||||
{
|
||||
BDRVQEDState *s = bs->opaque;
|
||||
uint64_t old_image_size;
|
||||
@ -1526,11 +1526,12 @@ static int bdrv_qed_truncate(BlockDriverState *bs, int64_t offset)
|
||||
|
||||
if (!qed_is_image_size_valid(offset, s->header.cluster_size,
|
||||
s->header.table_size)) {
|
||||
error_setg(errp, "Invalid image size specified");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Shrinking is currently not supported */
|
||||
if ((uint64_t)offset < s->header.image_size) {
|
||||
error_setg(errp, "Shrinking images is currently not supported");
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
@ -1539,6 +1540,7 @@ static int bdrv_qed_truncate(BlockDriverState *bs, int64_t offset)
|
||||
ret = qed_write_header_sync(s);
|
||||
if (ret < 0) {
|
||||
s->header.image_size = old_image_size;
|
||||
error_setg_errno(errp, -ret, "Failed to update the image size");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
@ -327,21 +327,23 @@ static void raw_refresh_limits(BlockDriverState *bs, Error **errp)
|
||||
}
|
||||
}
|
||||
|
||||
static int raw_truncate(BlockDriverState *bs, int64_t offset)
|
||||
static int raw_truncate(BlockDriverState *bs, int64_t offset, Error **errp)
|
||||
{
|
||||
BDRVRawState *s = bs->opaque;
|
||||
|
||||
if (s->has_size) {
|
||||
error_setg(errp, "Cannot resize fixed-size raw disks");
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
if (INT64_MAX - offset < s->offset) {
|
||||
error_setg(errp, "Disk size too large for the chosen offset");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
s->size = offset;
|
||||
offset += s->offset;
|
||||
return bdrv_truncate(bs->file, offset);
|
||||
return bdrv_truncate(bs->file, offset, errp);
|
||||
}
|
||||
|
||||
static int raw_media_changed(BlockDriverState *bs)
|
||||
|
@ -916,13 +916,14 @@ static int64_t qemu_rbd_getlength(BlockDriverState *bs)
|
||||
return info.size;
|
||||
}
|
||||
|
||||
static int qemu_rbd_truncate(BlockDriverState *bs, int64_t offset)
|
||||
static int qemu_rbd_truncate(BlockDriverState *bs, int64_t offset, Error **errp)
|
||||
{
|
||||
BDRVRBDState *s = bs->opaque;
|
||||
int r;
|
||||
|
||||
r = rbd_resize(s->image, offset);
|
||||
if (r < 0) {
|
||||
error_setg_errno(errp, -r, "Failed to resize file");
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -2159,9 +2159,8 @@ static int64_t sd_getlength(BlockDriverState *bs)
|
||||
return s->inode.vdi_size;
|
||||
}
|
||||
|
||||
static int sd_truncate(BlockDriverState *bs, int64_t offset)
|
||||
static int sd_truncate(BlockDriverState *bs, int64_t offset, Error **errp)
|
||||
{
|
||||
Error *local_err = NULL;
|
||||
BDRVSheepdogState *s = bs->opaque;
|
||||
int ret, fd;
|
||||
unsigned int datalen;
|
||||
@ -2169,16 +2168,15 @@ static int sd_truncate(BlockDriverState *bs, int64_t offset)
|
||||
|
||||
max_vdi_size = (UINT64_C(1) << s->inode.block_size_shift) * MAX_DATA_OBJS;
|
||||
if (offset < s->inode.vdi_size) {
|
||||
error_report("shrinking is not supported");
|
||||
error_setg(errp, "shrinking is not supported");
|
||||
return -EINVAL;
|
||||
} else if (offset > max_vdi_size) {
|
||||
error_report("too big image size");
|
||||
error_setg(errp, "too big image size");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
fd = connect_to_sdog(s, &local_err);
|
||||
fd = connect_to_sdog(s, errp);
|
||||
if (fd < 0) {
|
||||
error_report_err(local_err);
|
||||
return fd;
|
||||
}
|
||||
|
||||
@ -2191,7 +2189,7 @@ static int sd_truncate(BlockDriverState *bs, int64_t offset)
|
||||
close(fd);
|
||||
|
||||
if (ret < 0) {
|
||||
error_report("failed to update an inode.");
|
||||
error_setg_errno(errp, -ret, "failed to update an inode");
|
||||
}
|
||||
|
||||
return ret;
|
||||
@ -2456,7 +2454,7 @@ static coroutine_fn int sd_co_writev(BlockDriverState *bs, int64_t sector_num,
|
||||
BDRVSheepdogState *s = bs->opaque;
|
||||
|
||||
if (offset > s->inode.vdi_size) {
|
||||
ret = sd_truncate(bs, offset);
|
||||
ret = sd_truncate(bs, offset, NULL);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
@ -832,9 +832,9 @@ static int vdi_create(const char *filename, QemuOpts *opts, Error **errp)
|
||||
}
|
||||
|
||||
if (image_type == VDI_TYPE_STATIC) {
|
||||
ret = blk_truncate(blk, offset + blocks * block_size);
|
||||
ret = blk_truncate(blk, offset + blocks * block_size, errp);
|
||||
if (ret < 0) {
|
||||
error_setg(errp, "Failed to statically allocate %s", filename);
|
||||
error_prepend(errp, "Failed to statically allocate %s", filename);
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
@ -548,7 +548,7 @@ static int vhdx_log_flush(BlockDriverState *bs, BDRVVHDXState *s,
|
||||
if (new_file_size % (1024*1024)) {
|
||||
/* round up to nearest 1MB boundary */
|
||||
new_file_size = ((new_file_size >> 20) + 1) << 20;
|
||||
bdrv_truncate(bs->file, new_file_size);
|
||||
bdrv_truncate(bs->file, new_file_size, NULL);
|
||||
}
|
||||
}
|
||||
qemu_vfree(desc_entries);
|
||||
|
25
block/vhdx.c
25
block/vhdx.c
@ -1171,7 +1171,7 @@ static int vhdx_allocate_block(BlockDriverState *bs, BDRVVHDXState *s,
|
||||
/* per the spec, the address for a block is in units of 1MB */
|
||||
*new_offset = ROUND_UP(*new_offset, 1024 * 1024);
|
||||
|
||||
return bdrv_truncate(bs->file, *new_offset + s->block_size);
|
||||
return bdrv_truncate(bs->file, *new_offset + s->block_size, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1586,7 +1586,7 @@ exit:
|
||||
static int vhdx_create_bat(BlockBackend *blk, BDRVVHDXState *s,
|
||||
uint64_t image_size, VHDXImageType type,
|
||||
bool use_zero_blocks, uint64_t file_offset,
|
||||
uint32_t length)
|
||||
uint32_t length, Error **errp)
|
||||
{
|
||||
int ret = 0;
|
||||
uint64_t data_file_offset;
|
||||
@ -1607,16 +1607,17 @@ static int vhdx_create_bat(BlockBackend *blk, BDRVVHDXState *s,
|
||||
if (type == VHDX_TYPE_DYNAMIC) {
|
||||
/* All zeroes, so we can just extend the file - the end of the BAT
|
||||
* is the furthest thing we have written yet */
|
||||
ret = blk_truncate(blk, data_file_offset);
|
||||
ret = blk_truncate(blk, data_file_offset, errp);
|
||||
if (ret < 0) {
|
||||
goto exit;
|
||||
}
|
||||
} else if (type == VHDX_TYPE_FIXED) {
|
||||
ret = blk_truncate(blk, data_file_offset + image_size);
|
||||
ret = blk_truncate(blk, data_file_offset + image_size, errp);
|
||||
if (ret < 0) {
|
||||
goto exit;
|
||||
}
|
||||
} else {
|
||||
error_setg(errp, "Unsupported image type");
|
||||
ret = -ENOTSUP;
|
||||
goto exit;
|
||||
}
|
||||
@ -1627,6 +1628,7 @@ static int vhdx_create_bat(BlockBackend *blk, BDRVVHDXState *s,
|
||||
/* for a fixed file, the default BAT entry is not zero */
|
||||
s->bat = g_try_malloc0(length);
|
||||
if (length && s->bat == NULL) {
|
||||
error_setg(errp, "Failed to allocate memory for the BAT");
|
||||
ret = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
@ -1646,6 +1648,7 @@ static int vhdx_create_bat(BlockBackend *blk, BDRVVHDXState *s,
|
||||
}
|
||||
ret = blk_pwrite(blk, file_offset, s->bat, length, 0);
|
||||
if (ret < 0) {
|
||||
error_setg_errno(errp, -ret, "Failed to write the BAT");
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
@ -1671,7 +1674,8 @@ static int vhdx_create_new_region_table(BlockBackend *blk,
|
||||
uint32_t log_size,
|
||||
bool use_zero_blocks,
|
||||
VHDXImageType type,
|
||||
uint64_t *metadata_offset)
|
||||
uint64_t *metadata_offset,
|
||||
Error **errp)
|
||||
{
|
||||
int ret = 0;
|
||||
uint32_t offset = 0;
|
||||
@ -1740,7 +1744,7 @@ static int vhdx_create_new_region_table(BlockBackend *blk,
|
||||
/* The region table gives us the data we need to create the BAT,
|
||||
* so do that now */
|
||||
ret = vhdx_create_bat(blk, s, image_size, type, use_zero_blocks,
|
||||
bat_file_offset, bat_length);
|
||||
bat_file_offset, bat_length, errp);
|
||||
if (ret < 0) {
|
||||
goto exit;
|
||||
}
|
||||
@ -1749,12 +1753,14 @@ static int vhdx_create_new_region_table(BlockBackend *blk,
|
||||
ret = blk_pwrite(blk, VHDX_REGION_TABLE_OFFSET, buffer,
|
||||
VHDX_HEADER_BLOCK_SIZE, 0);
|
||||
if (ret < 0) {
|
||||
error_setg_errno(errp, -ret, "Failed to write first region table");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ret = blk_pwrite(blk, VHDX_REGION_TABLE2_OFFSET, buffer,
|
||||
VHDX_HEADER_BLOCK_SIZE, 0);
|
||||
if (ret < 0) {
|
||||
error_setg_errno(errp, -ret, "Failed to write second region table");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
@ -1825,6 +1831,7 @@ static int vhdx_create(const char *filename, QemuOpts *opts, Error **errp)
|
||||
ret = -ENOTSUP;
|
||||
goto exit;
|
||||
} else {
|
||||
error_setg(errp, "Invalid subformat '%s'", type);
|
||||
ret = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
@ -1879,12 +1886,14 @@ static int vhdx_create(const char *filename, QemuOpts *opts, Error **errp)
|
||||
ret = blk_pwrite(blk, VHDX_FILE_ID_OFFSET, &signature, sizeof(signature),
|
||||
0);
|
||||
if (ret < 0) {
|
||||
error_setg_errno(errp, -ret, "Failed to write file signature");
|
||||
goto delete_and_exit;
|
||||
}
|
||||
if (creator) {
|
||||
ret = blk_pwrite(blk, VHDX_FILE_ID_OFFSET + sizeof(signature),
|
||||
creator, creator_items * sizeof(gunichar2), 0);
|
||||
if (ret < 0) {
|
||||
error_setg_errno(errp, -ret, "Failed to write creator field");
|
||||
goto delete_and_exit;
|
||||
}
|
||||
}
|
||||
@ -1893,13 +1902,14 @@ static int vhdx_create(const char *filename, QemuOpts *opts, Error **errp)
|
||||
/* Creates (B),(C) */
|
||||
ret = vhdx_create_new_headers(blk, image_size, log_size);
|
||||
if (ret < 0) {
|
||||
error_setg_errno(errp, -ret, "Failed to write image headers");
|
||||
goto delete_and_exit;
|
||||
}
|
||||
|
||||
/* Creates (D),(E),(G) explicitly. (F) created as by-product */
|
||||
ret = vhdx_create_new_region_table(blk, image_size, block_size, 512,
|
||||
log_size, use_zero_blocks, image_type,
|
||||
&metadata_offset);
|
||||
&metadata_offset, errp);
|
||||
if (ret < 0) {
|
||||
goto delete_and_exit;
|
||||
}
|
||||
@ -1908,6 +1918,7 @@ static int vhdx_create(const char *filename, QemuOpts *opts, Error **errp)
|
||||
ret = vhdx_create_new_metadata(blk, image_size, block_size, 512,
|
||||
metadata_offset, image_type);
|
||||
if (ret < 0) {
|
||||
error_setg_errno(errp, -ret, "Failed to initialize metadata");
|
||||
goto delete_and_exit;
|
||||
}
|
||||
|
||||
|
13
block/vmdk.c
13
block/vmdk.c
@ -1714,10 +1714,7 @@ static int vmdk_create_extent(const char *filename, int64_t filesize,
|
||||
blk_set_allow_write_beyond_eof(blk, true);
|
||||
|
||||
if (flat) {
|
||||
ret = blk_truncate(blk, filesize);
|
||||
if (ret < 0) {
|
||||
error_setg_errno(errp, -ret, "Could not truncate file");
|
||||
}
|
||||
ret = blk_truncate(blk, filesize, errp);
|
||||
goto exit;
|
||||
}
|
||||
magic = cpu_to_be32(VMDK4_MAGIC);
|
||||
@ -1780,9 +1777,8 @@ static int vmdk_create_extent(const char *filename, int64_t filesize,
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ret = blk_truncate(blk, le64_to_cpu(header.grain_offset) << 9);
|
||||
ret = blk_truncate(blk, le64_to_cpu(header.grain_offset) << 9, errp);
|
||||
if (ret < 0) {
|
||||
error_setg_errno(errp, -ret, "Could not truncate file");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
@ -2090,10 +2086,7 @@ static int vmdk_create(const char *filename, QemuOpts *opts, Error **errp)
|
||||
/* bdrv_pwrite write padding zeros to align to sector, we don't need that
|
||||
* for description file */
|
||||
if (desc_offset == 0) {
|
||||
ret = blk_truncate(new_blk, desc_len);
|
||||
if (ret < 0) {
|
||||
error_setg_errno(errp, -ret, "Could not truncate file");
|
||||
}
|
||||
ret = blk_truncate(new_blk, desc_len, errp);
|
||||
}
|
||||
exit:
|
||||
if (new_blk) {
|
||||
|
13
block/vpc.c
13
block/vpc.c
@ -851,20 +851,21 @@ static int create_dynamic_disk(BlockBackend *blk, uint8_t *buf,
|
||||
}
|
||||
|
||||
static int create_fixed_disk(BlockBackend *blk, uint8_t *buf,
|
||||
int64_t total_size)
|
||||
int64_t total_size, Error **errp)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* Add footer to total size */
|
||||
total_size += HEADER_SIZE;
|
||||
|
||||
ret = blk_truncate(blk, total_size);
|
||||
ret = blk_truncate(blk, total_size, errp);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = blk_pwrite(blk, total_size - HEADER_SIZE, buf, HEADER_SIZE, 0);
|
||||
if (ret < 0) {
|
||||
error_setg_errno(errp, -ret, "Unable to write VHD header");
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -996,11 +997,11 @@ static int vpc_create(const char *filename, QemuOpts *opts, Error **errp)
|
||||
|
||||
if (disk_type == VHD_DYNAMIC) {
|
||||
ret = create_dynamic_disk(blk, buf, total_sectors);
|
||||
if (ret < 0) {
|
||||
error_setg(errp, "Unable to create or write VHD header");
|
||||
}
|
||||
} else {
|
||||
ret = create_fixed_disk(blk, buf, total_size);
|
||||
}
|
||||
if (ret < 0) {
|
||||
error_setg(errp, "Unable to create or write VHD header");
|
||||
ret = create_fixed_disk(blk, buf, total_size, errp);
|
||||
}
|
||||
|
||||
out:
|
||||
|
21
blockdev.c
21
blockdev.c
@ -2930,26 +2930,7 @@ void qmp_block_resize(bool has_device, const char *device,
|
||||
/* complete all in-flight operations before resizing the device */
|
||||
bdrv_drain_all();
|
||||
|
||||
ret = blk_truncate(blk, size);
|
||||
switch (ret) {
|
||||
case 0:
|
||||
break;
|
||||
case -ENOMEDIUM:
|
||||
error_setg(errp, QERR_DEVICE_HAS_NO_MEDIUM, device);
|
||||
break;
|
||||
case -ENOTSUP:
|
||||
error_setg(errp, QERR_UNSUPPORTED);
|
||||
break;
|
||||
case -EACCES:
|
||||
error_setg(errp, "Device '%s' is read only", device);
|
||||
break;
|
||||
case -EBUSY:
|
||||
error_setg(errp, QERR_DEVICE_IN_USE, device);
|
||||
break;
|
||||
default:
|
||||
error_setg_errno(errp, -ret, "Could not resize");
|
||||
break;
|
||||
}
|
||||
ret = blk_truncate(blk, size, errp);
|
||||
|
||||
out:
|
||||
blk_unref(blk);
|
||||
|
@ -294,7 +294,7 @@ BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs,
|
||||
const char *backing_file);
|
||||
int bdrv_get_backing_file_depth(BlockDriverState *bs);
|
||||
void bdrv_refresh_filename(BlockDriverState *bs);
|
||||
int bdrv_truncate(BdrvChild *child, int64_t offset);
|
||||
int bdrv_truncate(BdrvChild *child, int64_t offset, Error **errp);
|
||||
int64_t bdrv_nb_sectors(BlockDriverState *bs);
|
||||
int64_t bdrv_getlength(BlockDriverState *bs);
|
||||
int64_t bdrv_get_allocated_file_size(BlockDriverState *bs);
|
||||
|
@ -196,7 +196,7 @@ struct BlockDriver {
|
||||
int coroutine_fn (*bdrv_co_flush_to_os)(BlockDriverState *bs);
|
||||
|
||||
const char *protocol_name;
|
||||
int (*bdrv_truncate)(BlockDriverState *bs, int64_t offset);
|
||||
int (*bdrv_truncate)(BlockDriverState *bs, int64_t offset, Error **errp);
|
||||
|
||||
int64_t (*bdrv_getlength)(BlockDriverState *bs);
|
||||
bool has_variable_length;
|
||||
@ -252,7 +252,7 @@ struct BlockDriver {
|
||||
* Returns 0 for completed check, -errno for internal errors.
|
||||
* The check results are stored in result.
|
||||
*/
|
||||
int (*bdrv_check)(BlockDriverState* bs, BdrvCheckResult *result,
|
||||
int (*bdrv_check)(BlockDriverState *bs, BdrvCheckResult *result,
|
||||
BdrvCheckMode fix);
|
||||
|
||||
int (*bdrv_amend_options)(BlockDriverState *bs, QemuOpts *opts,
|
||||
@ -454,13 +454,13 @@ struct BdrvChildRole {
|
||||
/* Returns a name that is supposedly more useful for human users than the
|
||||
* node name for identifying the node in question (in particular, a BB
|
||||
* name), or NULL if the parent can't provide a better name. */
|
||||
const char* (*get_name)(BdrvChild *child);
|
||||
const char *(*get_name)(BdrvChild *child);
|
||||
|
||||
/* Returns a malloced string that describes the parent of the child for a
|
||||
* human reader. This could be a node-name, BlockBackend name, qdev ID or
|
||||
* QOM path of the device owning the BlockBackend, job type and ID etc. The
|
||||
* caller is responsible for freeing the memory. */
|
||||
char* (*get_parent_desc)(BdrvChild *child);
|
||||
char *(*get_parent_desc)(BdrvChild *child);
|
||||
|
||||
/*
|
||||
* If this pair of functions is implemented, the parent doesn't issue new
|
||||
|
@ -225,7 +225,7 @@ int coroutine_fn blk_co_pwrite_zeroes(BlockBackend *blk, int64_t offset,
|
||||
int count, BdrvRequestFlags flags);
|
||||
int blk_pwrite_compressed(BlockBackend *blk, int64_t offset, const void *buf,
|
||||
int count);
|
||||
int blk_truncate(BlockBackend *blk, int64_t offset);
|
||||
int blk_truncate(BlockBackend *blk, int64_t offset, Error **errp);
|
||||
int blk_pdiscard(BlockBackend *blk, int64_t offset, int count);
|
||||
int blk_save_vmstate(BlockBackend *blk, const uint8_t *buf,
|
||||
int64_t pos, int size);
|
||||
|
93
qemu-img.c
93
qemu-img.c
@ -1554,9 +1554,15 @@ static int convert_iteration_sectors(ImgConvertState *s, int64_t sector_num)
|
||||
|
||||
if (s->sector_next_status <= sector_num) {
|
||||
BlockDriverState *file;
|
||||
ret = bdrv_get_block_status(blk_bs(s->src[src_cur]),
|
||||
sector_num - src_cur_offset,
|
||||
n, &n, &file);
|
||||
if (s->target_has_backing) {
|
||||
ret = bdrv_get_block_status(blk_bs(s->src[src_cur]),
|
||||
sector_num - src_cur_offset,
|
||||
n, &n, &file);
|
||||
} else {
|
||||
ret = bdrv_get_block_status_above(blk_bs(s->src[src_cur]), NULL,
|
||||
sector_num - src_cur_offset,
|
||||
n, &n, &file);
|
||||
}
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
@ -1565,26 +1571,8 @@ static int convert_iteration_sectors(ImgConvertState *s, int64_t sector_num)
|
||||
s->status = BLK_ZERO;
|
||||
} else if (ret & BDRV_BLOCK_DATA) {
|
||||
s->status = BLK_DATA;
|
||||
} else if (!s->target_has_backing) {
|
||||
/* Without a target backing file we must copy over the contents of
|
||||
* the backing file as well. */
|
||||
/* Check block status of the backing file chain to avoid
|
||||
* needlessly reading zeroes and limiting the iteration to the
|
||||
* buffer size */
|
||||
ret = bdrv_get_block_status_above(blk_bs(s->src[src_cur]), NULL,
|
||||
sector_num - src_cur_offset,
|
||||
n, &n, &file);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (ret & BDRV_BLOCK_ZERO) {
|
||||
s->status = BLK_ZERO;
|
||||
} else {
|
||||
s->status = BLK_DATA;
|
||||
}
|
||||
} else {
|
||||
s->status = BLK_BACKING_FILE;
|
||||
s->status = s->target_has_backing ? BLK_BACKING_FILE : BLK_DATA;
|
||||
}
|
||||
|
||||
s->sector_next_status = sector_num + n;
|
||||
@ -1661,6 +1649,8 @@ static int coroutine_fn convert_co_write(ImgConvertState *s, int64_t sector_num,
|
||||
|
||||
while (nb_sectors > 0) {
|
||||
int n = nb_sectors;
|
||||
BdrvRequestFlags flags = s->compressed ? BDRV_REQ_WRITE_COMPRESSED : 0;
|
||||
|
||||
switch (status) {
|
||||
case BLK_BACKING_FILE:
|
||||
/* If we have a backing file, leave clusters unallocated that are
|
||||
@ -1670,43 +1660,24 @@ static int coroutine_fn convert_co_write(ImgConvertState *s, int64_t sector_num,
|
||||
break;
|
||||
|
||||
case BLK_DATA:
|
||||
/* We must always write compressed clusters as a whole, so don't
|
||||
* try to find zeroed parts in the buffer. We can only save the
|
||||
* write if the buffer is completely zeroed and we're allowed to
|
||||
* keep the target sparse. */
|
||||
if (s->compressed) {
|
||||
if (s->has_zero_init && s->min_sparse &&
|
||||
buffer_is_zero(buf, n * BDRV_SECTOR_SIZE))
|
||||
{
|
||||
assert(!s->target_has_backing);
|
||||
break;
|
||||
}
|
||||
|
||||
iov.iov_base = buf;
|
||||
iov.iov_len = n << BDRV_SECTOR_BITS;
|
||||
qemu_iovec_init_external(&qiov, &iov, 1);
|
||||
|
||||
ret = blk_co_pwritev(s->target, sector_num << BDRV_SECTOR_BITS,
|
||||
n << BDRV_SECTOR_BITS, &qiov,
|
||||
BDRV_REQ_WRITE_COMPRESSED);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* If there is real non-zero data or we're told to keep the target
|
||||
* fully allocated (-S 0), we must write it. Otherwise we can treat
|
||||
* it as zero sectors. */
|
||||
/* If we're told to keep the target fully allocated (-S 0) or there
|
||||
* is real non-zero data, we must write it. Otherwise we can treat
|
||||
* it as zero sectors.
|
||||
* Compressed clusters need to be written as a whole, so in that
|
||||
* case we can only save the write if the buffer is completely
|
||||
* zeroed. */
|
||||
if (!s->min_sparse ||
|
||||
is_allocated_sectors_min(buf, n, &n, s->min_sparse))
|
||||
(!s->compressed &&
|
||||
is_allocated_sectors_min(buf, n, &n, s->min_sparse)) ||
|
||||
(s->compressed &&
|
||||
!buffer_is_zero(buf, n * BDRV_SECTOR_SIZE)))
|
||||
{
|
||||
iov.iov_base = buf;
|
||||
iov.iov_len = n << BDRV_SECTOR_BITS;
|
||||
qemu_iovec_init_external(&qiov, &iov, 1);
|
||||
|
||||
ret = blk_co_pwritev(s->target, sector_num << BDRV_SECTOR_BITS,
|
||||
n << BDRV_SECTOR_BITS, &qiov, 0);
|
||||
n << BDRV_SECTOR_BITS, &qiov, flags);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
@ -1716,6 +1687,7 @@ static int coroutine_fn convert_co_write(ImgConvertState *s, int64_t sector_num,
|
||||
|
||||
case BLK_ZERO:
|
||||
if (s->has_zero_init) {
|
||||
assert(!s->target_has_backing);
|
||||
break;
|
||||
}
|
||||
ret = blk_co_pwrite_zeroes(s->target,
|
||||
@ -3464,20 +3436,11 @@ static int img_resize(int argc, char **argv)
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = blk_truncate(blk, total_size);
|
||||
switch (ret) {
|
||||
case 0:
|
||||
ret = blk_truncate(blk, total_size, &err);
|
||||
if (!ret) {
|
||||
qprintf(quiet, "Image resized.\n");
|
||||
break;
|
||||
case -ENOTSUP:
|
||||
error_report("This image does not support resize");
|
||||
break;
|
||||
case -EACCES:
|
||||
error_report("Image is read-only");
|
||||
break;
|
||||
default:
|
||||
error_report("Error resizing image: %s", strerror(-ret));
|
||||
break;
|
||||
} else {
|
||||
error_report_err(err);
|
||||
}
|
||||
out:
|
||||
blk_unref(blk);
|
||||
|
@ -84,7 +84,8 @@ with or without a command shows help and lists the supported formats
|
||||
@item -p
|
||||
display progress bar (compare, convert and rebase commands only).
|
||||
If the @var{-p} option is not used for a command that supports it, the
|
||||
progress is reported when the process receives a @code{SIGUSR1} signal.
|
||||
progress is reported when the process receives a @code{SIGUSR1} or
|
||||
@code{SIGINFO} signal.
|
||||
@item -q
|
||||
Quiet mode - do not print any output (except errors). There's no progress bar
|
||||
in case both @var{-q} and @var{-p} options are used.
|
||||
|
@ -1567,6 +1567,7 @@ static const cmdinfo_t flush_cmd = {
|
||||
|
||||
static int truncate_f(BlockBackend *blk, int argc, char **argv)
|
||||
{
|
||||
Error *local_err = NULL;
|
||||
int64_t offset;
|
||||
int ret;
|
||||
|
||||
@ -1576,9 +1577,9 @@ static int truncate_f(BlockBackend *blk, int argc, char **argv)
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = blk_truncate(blk, offset);
|
||||
ret = blk_truncate(blk, offset, &local_err);
|
||||
if (ret < 0) {
|
||||
printf("truncate: %s\n", strerror(-ret));
|
||||
error_report_err(local_err);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -42,16 +42,18 @@ _supported_fmt qcow2
|
||||
_supported_proto generic
|
||||
_supported_os Linux
|
||||
|
||||
# Intentionally create an unaligned image
|
||||
IMGOPTS="compat=1.1"
|
||||
IMG_SIZE=64M
|
||||
IMG_SIZE=$((64 * 1024 * 1024 + 512))
|
||||
|
||||
echo
|
||||
echo "=== Testing snapshotting an image with zero clusters ==="
|
||||
echo "=== Testing cluster discards ==="
|
||||
echo
|
||||
_make_test_img $IMG_SIZE
|
||||
# Write some normal clusters, zero them (creating preallocated zero clusters)
|
||||
# and discard those
|
||||
$QEMU_IO -c "write 0 256k" -c "write -z 0 256k" -c "discard 0 256k" "$TEST_IMG" \
|
||||
# Write some normal clusters, zero some of them (creating preallocated
|
||||
# zero clusters) and discard everything. Everything should now read as 0.
|
||||
$QEMU_IO -c "write 0 256k" -c "write -z 0 256k" -c "write 64M 512" \
|
||||
-c "discard 0 $IMG_SIZE" -c "read -P 0 0 $IMG_SIZE" "$TEST_IMG" \
|
||||
| _filter_qemu_io
|
||||
# Check the image (there shouldn't be any leaks)
|
||||
_check_test_img
|
||||
|
@ -1,13 +1,17 @@
|
||||
QA output created by 066
|
||||
|
||||
=== Testing snapshotting an image with zero clusters ===
|
||||
=== Testing cluster discards ===
|
||||
|
||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
|
||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67109376
|
||||
wrote 262144/262144 bytes at offset 0
|
||||
256 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
wrote 262144/262144 bytes at offset 0
|
||||
256 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
discard 262144/262144 bytes at offset 0
|
||||
256 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
wrote 512/512 bytes at offset 67108864
|
||||
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
discard 67109376/67109376 bytes at offset 0
|
||||
64 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
read 67109376/67109376 bytes at offset 0
|
||||
64 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
No errors were found on the image.
|
||||
*** done
|
||||
|
@ -86,7 +86,8 @@ s/ .*//p
|
||||
elif $xgroup
|
||||
then
|
||||
# arg after -x
|
||||
[ ! -s $tmp.list ] && ls [0-9][0-9][0-9] [0-9][0-9][0-9][0-9] >$tmp.list 2>/dev/null
|
||||
# Populate $tmp.list with all tests
|
||||
awk '/^[0-9]{3,}/ {print $1}' "${source_iotests}/group" > $tmp.list 2>/dev/null
|
||||
group_list=`sed -n <"$source_iotests/group" -e 's/$/ /' -e "/^[0-9][0-9][0-9].* $r /"'{
|
||||
s/ .*//p
|
||||
}'`
|
||||
@ -138,7 +139,7 @@ common options
|
||||
-v verbose
|
||||
-d debug
|
||||
|
||||
check options
|
||||
image format options
|
||||
-raw test raw (default)
|
||||
-bochs test bochs
|
||||
-cloop test cloop
|
||||
@ -150,14 +151,18 @@ check options
|
||||
-vpc test vpc
|
||||
-vhdx test vhdx
|
||||
-vmdk test vmdk
|
||||
-luks test luks
|
||||
|
||||
image protocol options
|
||||
-file test file (default)
|
||||
-rbd test rbd
|
||||
-sheepdog test sheepdog
|
||||
-nbd test nbd
|
||||
-ssh test ssh
|
||||
-nfs test nfs
|
||||
-luks test luks
|
||||
-vxhs test vxhs
|
||||
|
||||
other options
|
||||
-xdiff graphical mode diff
|
||||
-nocache use O_DIRECT on backing file
|
||||
-misalign misalign memory allocations
|
||||
|
@ -88,6 +88,9 @@ static void progress_dummy_init(void)
|
||||
action.sa_handler = sigusr_print;
|
||||
action.sa_flags = 0;
|
||||
sigaction(SIGUSR1, &action, NULL);
|
||||
#ifdef SIGINFO
|
||||
sigaction(SIGINFO, &action, NULL);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* SIGUSR1 is SIG_IPI and gets blocked in qemu_init_main_loop(). In the
|
||||
|
Loading…
Reference in New Issue
Block a user