mirror of https://gitee.com/openkylin/qemu.git
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)
|
* 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;
|
BlockDriverState *bs = child->bs;
|
||||||
BlockDriver *drv = bs->drv;
|
BlockDriver *drv = bs->drv;
|
||||||
|
@ -3315,14 +3315,22 @@ int bdrv_truncate(BdrvChild *child, int64_t offset)
|
||||||
|
|
||||||
assert(child->perm & BLK_PERM_RESIZE);
|
assert(child->perm & BLK_PERM_RESIZE);
|
||||||
|
|
||||||
if (!drv)
|
if (!drv) {
|
||||||
|
error_setg(errp, "No medium inserted");
|
||||||
return -ENOMEDIUM;
|
return -ENOMEDIUM;
|
||||||
if (!drv->bdrv_truncate)
|
}
|
||||||
|
if (!drv->bdrv_truncate) {
|
||||||
|
error_setg(errp, "Image format driver does not support resize");
|
||||||
return -ENOTSUP;
|
return -ENOTSUP;
|
||||||
if (bs->read_only)
|
}
|
||||||
|
if (bs->read_only) {
|
||||||
|
error_setg(errp, "Image is read-only");
|
||||||
return -EACCES;
|
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) {
|
if (ret == 0) {
|
||||||
ret = refresh_total_sectors(bs, offset >> BDRV_SECTOR_BITS);
|
ret = refresh_total_sectors(bs, offset >> BDRV_SECTOR_BITS);
|
||||||
bdrv_dirty_bitmap_truncate(bs);
|
bdrv_dirty_bitmap_truncate(bs);
|
||||||
|
|
|
@ -659,9 +659,9 @@ static int64_t blkdebug_getlength(BlockDriverState *bs)
|
||||||
return bdrv_getlength(bs->file->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)
|
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);
|
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)) {
|
if (!blk_is_available(blk)) {
|
||||||
|
error_setg(errp, "No medium inserted");
|
||||||
return -ENOMEDIUM;
|
return -ENOMEDIUM;
|
||||||
}
|
}
|
||||||
|
|
||||||
return bdrv_truncate(blk->root, offset);
|
return bdrv_truncate(blk->root, offset, errp);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void blk_pdiscard_entry(void *opaque)
|
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) {
|
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) {
|
if (ret) {
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -511,8 +511,9 @@ int bdrv_commit(BlockDriverState *bs)
|
||||||
* grow the backing file image if possible. If not possible,
|
* grow the backing file image if possible. If not possible,
|
||||||
* we must return an error */
|
* we must return an error */
|
||||||
if (length > backing_length) {
|
if (length > backing_length) {
|
||||||
ret = blk_truncate(backing, length);
|
ret = blk_truncate(backing, length, &local_err);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
|
error_report_err(local_err);
|
||||||
goto ro_cleanup;
|
goto ro_cleanup;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -381,7 +381,8 @@ static int block_crypto_create_generic(QCryptoBlockFormat format,
|
||||||
return ret;
|
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;
|
BlockCrypto *crypto = bs->opaque;
|
||||||
size_t payload_offset =
|
size_t payload_offset =
|
||||||
|
@ -389,7 +390,7 @@ static int block_crypto_truncate(BlockDriverState *bs, int64_t offset)
|
||||||
|
|
||||||
offset += payload_offset;
|
offset += payload_offset;
|
||||||
|
|
||||||
return bdrv_truncate(bs->file, offset);
|
return bdrv_truncate(bs->file, offset, errp);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void block_crypto_close(BlockDriverState *bs)
|
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;
|
BDRVRawState *s = bs->opaque;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
int ret;
|
||||||
|
|
||||||
if (fstat(s->fd, &st)) {
|
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 (S_ISREG(st.st_mode)) {
|
||||||
if (ftruncate(s->fd, offset) < 0) {
|
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)) {
|
} else if (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode)) {
|
||||||
if (offset > raw_getlength(bs)) {
|
if (offset > raw_getlength(bs)) {
|
||||||
return -EINVAL;
|
error_setg(errp, "Cannot grow device files");
|
||||||
}
|
return -EINVAL;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
|
error_setg(errp, "Resizing this file is not supported");
|
||||||
return -ENOTSUP;
|
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;
|
BDRVRawState *s = bs->opaque;
|
||||||
LONG low, high;
|
LONG low, high;
|
||||||
|
@ -475,11 +475,11 @@ static int raw_truncate(BlockDriverState *bs, int64_t offset)
|
||||||
*/
|
*/
|
||||||
dwPtrLow = SetFilePointer(s->hfile, low, &high, FILE_BEGIN);
|
dwPtrLow = SetFilePointer(s->hfile, low, &high, FILE_BEGIN);
|
||||||
if (dwPtrLow == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR) {
|
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;
|
return -EIO;
|
||||||
}
|
}
|
||||||
if (SetEndOfFile(s->hfile) == 0) {
|
if (SetEndOfFile(s->hfile) == 0) {
|
||||||
fprintf(stderr, "SetEndOfFile error: %lu\n", GetLastError());
|
error_setg_win32(errp, GetLastError(), "SetEndOfFile error");
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -1092,14 +1092,17 @@ static coroutine_fn int qemu_gluster_co_rw(BlockDriverState *bs,
|
||||||
return acb.ret;
|
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;
|
int ret;
|
||||||
BDRVGlusterState *s = bs->opaque;
|
BDRVGlusterState *s = bs->opaque;
|
||||||
|
|
||||||
ret = glfs_ftruncate(s->fd, offset);
|
ret = glfs_ftruncate(s->fd, offset);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
return -errno;
|
ret = -errno;
|
||||||
|
error_setg_errno(errp, -ret, "Failed to truncate file");
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
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;
|
IscsiLun *iscsilun = bs->opaque;
|
||||||
Error *local_err = NULL;
|
Error *local_err = NULL;
|
||||||
|
|
||||||
if (iscsilun->type != TYPE_DISK) {
|
if (iscsilun->type != TYPE_DISK) {
|
||||||
|
error_setg(errp, "Cannot resize non-disk iSCSI devices");
|
||||||
return -ENOTSUP;
|
return -ENOTSUP;
|
||||||
}
|
}
|
||||||
|
|
||||||
iscsi_readcapacity_sync(iscsilun, &local_err);
|
iscsi_readcapacity_sync(iscsilun, &local_err);
|
||||||
if (local_err != NULL) {
|
if (local_err != NULL) {
|
||||||
error_free(local_err);
|
error_propagate(errp, local_err);
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (offset > iscsi_getlength(bs)) {
|
if (offset > iscsi_getlength(bs)) {
|
||||||
|
error_setg(errp, "Cannot grow iSCSI devices");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -724,7 +724,7 @@ static void coroutine_fn mirror_run(void *opaque)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s->bdev_length > base_length) {
|
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) {
|
if (ret < 0) {
|
||||||
goto immediate_exit;
|
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);
|
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;
|
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
|
/* 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);
|
space << BDRV_SECTOR_BITS, 0);
|
||||||
} else {
|
} else {
|
||||||
ret = bdrv_truncate(bs->file,
|
ret = bdrv_truncate(bs->file,
|
||||||
(s->data_end + space) << BDRV_SECTOR_BITS);
|
(s->data_end + space) << BDRV_SECTOR_BITS,
|
||||||
|
NULL);
|
||||||
}
|
}
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -456,8 +457,10 @@ static int parallels_check(BlockDriverState *bs, BdrvCheckResult *res,
|
||||||
size - res->image_end_offset);
|
size - res->image_end_offset);
|
||||||
res->leaks += count;
|
res->leaks += count;
|
||||||
if (fix & BDRV_FIX_LEAKS) {
|
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) {
|
if (ret < 0) {
|
||||||
|
error_report_err(local_err);
|
||||||
res->check_errors++;
|
res->check_errors++;
|
||||||
return ret;
|
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);
|
blk_set_allow_write_beyond_eof(file, true);
|
||||||
|
|
||||||
ret = blk_truncate(file, 0);
|
ret = blk_truncate(file, 0, errp);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto exit;
|
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) ||
|
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;
|
s->prealloc_mode = PRL_PREALLOC_MODE_FALLOCATE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -739,7 +742,7 @@ static void parallels_close(BlockDriverState *bs)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bs->open_flags & BDRV_O_RDWR) {
|
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);
|
g_free(s->bat_dirty_bmap);
|
||||||
|
|
|
@ -473,7 +473,7 @@ static uint64_t get_cluster_offset(BlockDriverState *bs,
|
||||||
/* round to cluster size */
|
/* round to cluster size */
|
||||||
cluster_offset = (cluster_offset + s->cluster_size - 1) &
|
cluster_offset = (cluster_offset + s->cluster_size - 1) &
|
||||||
~(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
|
/* if encrypted, we must initialize the cluster
|
||||||
content which won't be written */
|
content which won't be written */
|
||||||
if (bs->encrypted &&
|
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);
|
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) {
|
if (ret < 0) {
|
||||||
goto exit;
|
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,
|
if (bdrv_pwrite_sync(bs->file, s->l1_table_offset, s->l1_table,
|
||||||
l1_length) < 0)
|
l1_length) < 0)
|
||||||
return -1;
|
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)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
|
|
@ -1728,14 +1728,17 @@ static int check_refblocks(BlockDriverState *bs, BdrvCheckResult *res,
|
||||||
|
|
||||||
if (fix & BDRV_FIX_ERRORS) {
|
if (fix & BDRV_FIX_ERRORS) {
|
||||||
int64_t new_nb_clusters;
|
int64_t new_nb_clusters;
|
||||||
|
Error *local_err = NULL;
|
||||||
|
|
||||||
if (offset > INT64_MAX - s->cluster_size) {
|
if (offset > INT64_MAX - s->cluster_size) {
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto resize_fail;
|
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) {
|
if (ret < 0) {
|
||||||
|
error_report_err(local_err);
|
||||||
goto resize_fail;
|
goto resize_fail;
|
||||||
}
|
}
|
||||||
size = bdrv_getlength(bs->file->bs);
|
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 */
|
/* 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) {
|
if (ret < 0) {
|
||||||
error_setg_errno(errp, -ret, "Could not resize image");
|
error_prepend(errp, "Could not resize image: ");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2515,7 +2515,12 @@ static coroutine_fn int qcow2_co_pdiscard(BlockDriverState *bs,
|
||||||
|
|
||||||
if (!QEMU_IS_ALIGNED(offset | count, s->cluster_size)) {
|
if (!QEMU_IS_ALIGNED(offset | count, s->cluster_size)) {
|
||||||
assert(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);
|
qemu_co_mutex_lock(&s->lock);
|
||||||
|
@ -2525,32 +2530,33 @@ static coroutine_fn int qcow2_co_pdiscard(BlockDriverState *bs,
|
||||||
return ret;
|
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;
|
BDRVQcow2State *s = bs->opaque;
|
||||||
int64_t new_l1_size;
|
int64_t new_l1_size;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (offset & 511) {
|
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;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* cannot proceed if image has snapshots */
|
/* cannot proceed if image has snapshots */
|
||||||
if (s->nb_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;
|
return -ENOTSUP;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* shrinking is currently not supported */
|
/* shrinking is currently not supported */
|
||||||
if (offset < bs->total_sectors * 512) {
|
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;
|
return -ENOTSUP;
|
||||||
}
|
}
|
||||||
|
|
||||||
new_l1_size = size_to_l1(s, offset);
|
new_l1_size = size_to_l1(s, offset);
|
||||||
ret = qcow2_grow_l1_table(bs, new_l1_size, true);
|
ret = qcow2_grow_l1_table(bs, new_l1_size, true);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
|
error_setg_errno(errp, -ret, "Failed to grow the L1 table");
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2559,6 +2565,7 @@ static int qcow2_truncate(BlockDriverState *bs, int64_t offset)
|
||||||
ret = bdrv_pwrite_sync(bs->file, offsetof(QCowHeader, size),
|
ret = bdrv_pwrite_sync(bs->file, offsetof(QCowHeader, size),
|
||||||
&offset, sizeof(uint64_t));
|
&offset, sizeof(uint64_t));
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
|
error_setg_errno(errp, -ret, "Failed to update the image size");
|
||||||
return ret;
|
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
|
/* align end of file to a sector boundary to ease reading with
|
||||||
sector based I/Os */
|
sector based I/Os */
|
||||||
cluster_offset = bdrv_getlength(bs->file->bs);
|
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);
|
buf = qemu_blockalign(bs, s->cluster_size);
|
||||||
|
@ -2674,6 +2681,7 @@ fail:
|
||||||
static int make_completely_empty(BlockDriverState *bs)
|
static int make_completely_empty(BlockDriverState *bs)
|
||||||
{
|
{
|
||||||
BDRVQcow2State *s = bs->opaque;
|
BDRVQcow2State *s = bs->opaque;
|
||||||
|
Error *local_err = NULL;
|
||||||
int ret, l1_clusters;
|
int ret, l1_clusters;
|
||||||
int64_t offset;
|
int64_t offset;
|
||||||
uint64_t *new_reftable = NULL;
|
uint64_t *new_reftable = NULL;
|
||||||
|
@ -2798,8 +2806,10 @@ static int make_completely_empty(BlockDriverState *bs)
|
||||||
goto fail;
|
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) {
|
if (ret < 0) {
|
||||||
|
error_report_err(local_err);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3273,9 +3283,10 @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = blk_truncate(blk, new_size);
|
ret = blk_truncate(blk, new_size, &local_err);
|
||||||
blk_unref(blk);
|
blk_unref(blk);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
|
error_report_err(local_err);
|
||||||
return ret;
|
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);
|
blk_set_allow_write_beyond_eof(blk, true);
|
||||||
|
|
||||||
/* File must start empty and grow, check truncate is supported */
|
/* File must start empty and grow, check truncate is supported */
|
||||||
ret = blk_truncate(blk, 0);
|
ret = blk_truncate(blk, 0, errp);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -1518,7 +1518,7 @@ static int coroutine_fn bdrv_qed_co_pwrite_zeroes(BlockDriverState *bs,
|
||||||
return cb.ret;
|
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;
|
BDRVQEDState *s = bs->opaque;
|
||||||
uint64_t old_image_size;
|
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,
|
if (!qed_is_image_size_valid(offset, s->header.cluster_size,
|
||||||
s->header.table_size)) {
|
s->header.table_size)) {
|
||||||
|
error_setg(errp, "Invalid image size specified");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Shrinking is currently not supported */
|
|
||||||
if ((uint64_t)offset < s->header.image_size) {
|
if ((uint64_t)offset < s->header.image_size) {
|
||||||
|
error_setg(errp, "Shrinking images is currently not supported");
|
||||||
return -ENOTSUP;
|
return -ENOTSUP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1539,6 +1540,7 @@ static int bdrv_qed_truncate(BlockDriverState *bs, int64_t offset)
|
||||||
ret = qed_write_header_sync(s);
|
ret = qed_write_header_sync(s);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
s->header.image_size = old_image_size;
|
s->header.image_size = old_image_size;
|
||||||
|
error_setg_errno(errp, -ret, "Failed to update the image size");
|
||||||
}
|
}
|
||||||
return ret;
|
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;
|
BDRVRawState *s = bs->opaque;
|
||||||
|
|
||||||
if (s->has_size) {
|
if (s->has_size) {
|
||||||
|
error_setg(errp, "Cannot resize fixed-size raw disks");
|
||||||
return -ENOTSUP;
|
return -ENOTSUP;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (INT64_MAX - offset < s->offset) {
|
if (INT64_MAX - offset < s->offset) {
|
||||||
|
error_setg(errp, "Disk size too large for the chosen offset");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
s->size = offset;
|
s->size = offset;
|
||||||
offset += s->offset;
|
offset += s->offset;
|
||||||
return bdrv_truncate(bs->file, offset);
|
return bdrv_truncate(bs->file, offset, errp);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int raw_media_changed(BlockDriverState *bs)
|
static int raw_media_changed(BlockDriverState *bs)
|
||||||
|
|
|
@ -916,13 +916,14 @@ static int64_t qemu_rbd_getlength(BlockDriverState *bs)
|
||||||
return info.size;
|
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;
|
BDRVRBDState *s = bs->opaque;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
r = rbd_resize(s->image, offset);
|
r = rbd_resize(s->image, offset);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
|
error_setg_errno(errp, -r, "Failed to resize file");
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2159,9 +2159,8 @@ static int64_t sd_getlength(BlockDriverState *bs)
|
||||||
return s->inode.vdi_size;
|
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;
|
BDRVSheepdogState *s = bs->opaque;
|
||||||
int ret, fd;
|
int ret, fd;
|
||||||
unsigned int datalen;
|
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;
|
max_vdi_size = (UINT64_C(1) << s->inode.block_size_shift) * MAX_DATA_OBJS;
|
||||||
if (offset < s->inode.vdi_size) {
|
if (offset < s->inode.vdi_size) {
|
||||||
error_report("shrinking is not supported");
|
error_setg(errp, "shrinking is not supported");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
} else if (offset > max_vdi_size) {
|
} else if (offset > max_vdi_size) {
|
||||||
error_report("too big image size");
|
error_setg(errp, "too big image size");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
fd = connect_to_sdog(s, &local_err);
|
fd = connect_to_sdog(s, errp);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
error_report_err(local_err);
|
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2191,7 +2189,7 @@ static int sd_truncate(BlockDriverState *bs, int64_t offset)
|
||||||
close(fd);
|
close(fd);
|
||||||
|
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
error_report("failed to update an inode.");
|
error_setg_errno(errp, -ret, "failed to update an inode");
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -2456,7 +2454,7 @@ static coroutine_fn int sd_co_writev(BlockDriverState *bs, int64_t sector_num,
|
||||||
BDRVSheepdogState *s = bs->opaque;
|
BDRVSheepdogState *s = bs->opaque;
|
||||||
|
|
||||||
if (offset > s->inode.vdi_size) {
|
if (offset > s->inode.vdi_size) {
|
||||||
ret = sd_truncate(bs, offset);
|
ret = sd_truncate(bs, offset, NULL);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -832,9 +832,9 @@ static int vdi_create(const char *filename, QemuOpts *opts, Error **errp)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (image_type == VDI_TYPE_STATIC) {
|
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) {
|
if (ret < 0) {
|
||||||
error_setg(errp, "Failed to statically allocate %s", filename);
|
error_prepend(errp, "Failed to statically allocate %s", filename);
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -548,7 +548,7 @@ static int vhdx_log_flush(BlockDriverState *bs, BDRVVHDXState *s,
|
||||||
if (new_file_size % (1024*1024)) {
|
if (new_file_size % (1024*1024)) {
|
||||||
/* round up to nearest 1MB boundary */
|
/* round up to nearest 1MB boundary */
|
||||||
new_file_size = ((new_file_size >> 20) + 1) << 20;
|
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);
|
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 */
|
/* per the spec, the address for a block is in units of 1MB */
|
||||||
*new_offset = ROUND_UP(*new_offset, 1024 * 1024);
|
*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,
|
static int vhdx_create_bat(BlockBackend *blk, BDRVVHDXState *s,
|
||||||
uint64_t image_size, VHDXImageType type,
|
uint64_t image_size, VHDXImageType type,
|
||||||
bool use_zero_blocks, uint64_t file_offset,
|
bool use_zero_blocks, uint64_t file_offset,
|
||||||
uint32_t length)
|
uint32_t length, Error **errp)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
uint64_t data_file_offset;
|
uint64_t data_file_offset;
|
||||||
|
@ -1607,16 +1607,17 @@ static int vhdx_create_bat(BlockBackend *blk, BDRVVHDXState *s,
|
||||||
if (type == VHDX_TYPE_DYNAMIC) {
|
if (type == VHDX_TYPE_DYNAMIC) {
|
||||||
/* All zeroes, so we can just extend the file - the end of the BAT
|
/* All zeroes, so we can just extend the file - the end of the BAT
|
||||||
* is the furthest thing we have written yet */
|
* 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) {
|
if (ret < 0) {
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
} else if (type == VHDX_TYPE_FIXED) {
|
} 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) {
|
if (ret < 0) {
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
error_setg(errp, "Unsupported image type");
|
||||||
ret = -ENOTSUP;
|
ret = -ENOTSUP;
|
||||||
goto exit;
|
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 */
|
/* for a fixed file, the default BAT entry is not zero */
|
||||||
s->bat = g_try_malloc0(length);
|
s->bat = g_try_malloc0(length);
|
||||||
if (length && s->bat == NULL) {
|
if (length && s->bat == NULL) {
|
||||||
|
error_setg(errp, "Failed to allocate memory for the BAT");
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
goto exit;
|
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);
|
ret = blk_pwrite(blk, file_offset, s->bat, length, 0);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
|
error_setg_errno(errp, -ret, "Failed to write the BAT");
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1671,7 +1674,8 @@ static int vhdx_create_new_region_table(BlockBackend *blk,
|
||||||
uint32_t log_size,
|
uint32_t log_size,
|
||||||
bool use_zero_blocks,
|
bool use_zero_blocks,
|
||||||
VHDXImageType type,
|
VHDXImageType type,
|
||||||
uint64_t *metadata_offset)
|
uint64_t *metadata_offset,
|
||||||
|
Error **errp)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
uint32_t offset = 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,
|
/* The region table gives us the data we need to create the BAT,
|
||||||
* so do that now */
|
* so do that now */
|
||||||
ret = vhdx_create_bat(blk, s, image_size, type, use_zero_blocks,
|
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) {
|
if (ret < 0) {
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
@ -1749,12 +1753,14 @@ static int vhdx_create_new_region_table(BlockBackend *blk,
|
||||||
ret = blk_pwrite(blk, VHDX_REGION_TABLE_OFFSET, buffer,
|
ret = blk_pwrite(blk, VHDX_REGION_TABLE_OFFSET, buffer,
|
||||||
VHDX_HEADER_BLOCK_SIZE, 0);
|
VHDX_HEADER_BLOCK_SIZE, 0);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
|
error_setg_errno(errp, -ret, "Failed to write first region table");
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = blk_pwrite(blk, VHDX_REGION_TABLE2_OFFSET, buffer,
|
ret = blk_pwrite(blk, VHDX_REGION_TABLE2_OFFSET, buffer,
|
||||||
VHDX_HEADER_BLOCK_SIZE, 0);
|
VHDX_HEADER_BLOCK_SIZE, 0);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
|
error_setg_errno(errp, -ret, "Failed to write second region table");
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1825,6 +1831,7 @@ static int vhdx_create(const char *filename, QemuOpts *opts, Error **errp)
|
||||||
ret = -ENOTSUP;
|
ret = -ENOTSUP;
|
||||||
goto exit;
|
goto exit;
|
||||||
} else {
|
} else {
|
||||||
|
error_setg(errp, "Invalid subformat '%s'", type);
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto exit;
|
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),
|
ret = blk_pwrite(blk, VHDX_FILE_ID_OFFSET, &signature, sizeof(signature),
|
||||||
0);
|
0);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
|
error_setg_errno(errp, -ret, "Failed to write file signature");
|
||||||
goto delete_and_exit;
|
goto delete_and_exit;
|
||||||
}
|
}
|
||||||
if (creator) {
|
if (creator) {
|
||||||
ret = blk_pwrite(blk, VHDX_FILE_ID_OFFSET + sizeof(signature),
|
ret = blk_pwrite(blk, VHDX_FILE_ID_OFFSET + sizeof(signature),
|
||||||
creator, creator_items * sizeof(gunichar2), 0);
|
creator, creator_items * sizeof(gunichar2), 0);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
|
error_setg_errno(errp, -ret, "Failed to write creator field");
|
||||||
goto delete_and_exit;
|
goto delete_and_exit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1893,13 +1902,14 @@ static int vhdx_create(const char *filename, QemuOpts *opts, Error **errp)
|
||||||
/* Creates (B),(C) */
|
/* Creates (B),(C) */
|
||||||
ret = vhdx_create_new_headers(blk, image_size, log_size);
|
ret = vhdx_create_new_headers(blk, image_size, log_size);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
|
error_setg_errno(errp, -ret, "Failed to write image headers");
|
||||||
goto delete_and_exit;
|
goto delete_and_exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Creates (D),(E),(G) explicitly. (F) created as by-product */
|
/* Creates (D),(E),(G) explicitly. (F) created as by-product */
|
||||||
ret = vhdx_create_new_region_table(blk, image_size, block_size, 512,
|
ret = vhdx_create_new_region_table(blk, image_size, block_size, 512,
|
||||||
log_size, use_zero_blocks, image_type,
|
log_size, use_zero_blocks, image_type,
|
||||||
&metadata_offset);
|
&metadata_offset, errp);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto delete_and_exit;
|
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,
|
ret = vhdx_create_new_metadata(blk, image_size, block_size, 512,
|
||||||
metadata_offset, image_type);
|
metadata_offset, image_type);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
|
error_setg_errno(errp, -ret, "Failed to initialize metadata");
|
||||||
goto delete_and_exit;
|
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);
|
blk_set_allow_write_beyond_eof(blk, true);
|
||||||
|
|
||||||
if (flat) {
|
if (flat) {
|
||||||
ret = blk_truncate(blk, filesize);
|
ret = blk_truncate(blk, filesize, errp);
|
||||||
if (ret < 0) {
|
|
||||||
error_setg_errno(errp, -ret, "Could not truncate file");
|
|
||||||
}
|
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
magic = cpu_to_be32(VMDK4_MAGIC);
|
magic = cpu_to_be32(VMDK4_MAGIC);
|
||||||
|
@ -1780,9 +1777,8 @@ static int vmdk_create_extent(const char *filename, int64_t filesize,
|
||||||
goto exit;
|
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) {
|
if (ret < 0) {
|
||||||
error_setg_errno(errp, -ret, "Could not truncate file");
|
|
||||||
goto exit;
|
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
|
/* bdrv_pwrite write padding zeros to align to sector, we don't need that
|
||||||
* for description file */
|
* for description file */
|
||||||
if (desc_offset == 0) {
|
if (desc_offset == 0) {
|
||||||
ret = blk_truncate(new_blk, desc_len);
|
ret = blk_truncate(new_blk, desc_len, errp);
|
||||||
if (ret < 0) {
|
|
||||||
error_setg_errno(errp, -ret, "Could not truncate file");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
exit:
|
exit:
|
||||||
if (new_blk) {
|
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,
|
static int create_fixed_disk(BlockBackend *blk, uint8_t *buf,
|
||||||
int64_t total_size)
|
int64_t total_size, Error **errp)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/* Add footer to total size */
|
/* Add footer to total size */
|
||||||
total_size += HEADER_SIZE;
|
total_size += HEADER_SIZE;
|
||||||
|
|
||||||
ret = blk_truncate(blk, total_size);
|
ret = blk_truncate(blk, total_size, errp);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = blk_pwrite(blk, total_size - HEADER_SIZE, buf, HEADER_SIZE, 0);
|
ret = blk_pwrite(blk, total_size - HEADER_SIZE, buf, HEADER_SIZE, 0);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
|
error_setg_errno(errp, -ret, "Unable to write VHD header");
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -996,11 +997,11 @@ static int vpc_create(const char *filename, QemuOpts *opts, Error **errp)
|
||||||
|
|
||||||
if (disk_type == VHD_DYNAMIC) {
|
if (disk_type == VHD_DYNAMIC) {
|
||||||
ret = create_dynamic_disk(blk, buf, total_sectors);
|
ret = create_dynamic_disk(blk, buf, total_sectors);
|
||||||
|
if (ret < 0) {
|
||||||
|
error_setg(errp, "Unable to create or write VHD header");
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
ret = create_fixed_disk(blk, buf, total_size);
|
ret = create_fixed_disk(blk, buf, total_size, errp);
|
||||||
}
|
|
||||||
if (ret < 0) {
|
|
||||||
error_setg(errp, "Unable to create or write VHD header");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
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 */
|
/* complete all in-flight operations before resizing the device */
|
||||||
bdrv_drain_all();
|
bdrv_drain_all();
|
||||||
|
|
||||||
ret = blk_truncate(blk, size);
|
ret = blk_truncate(blk, size, errp);
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
out:
|
out:
|
||||||
blk_unref(blk);
|
blk_unref(blk);
|
||||||
|
|
|
@ -294,7 +294,7 @@ BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs,
|
||||||
const char *backing_file);
|
const char *backing_file);
|
||||||
int bdrv_get_backing_file_depth(BlockDriverState *bs);
|
int bdrv_get_backing_file_depth(BlockDriverState *bs);
|
||||||
void bdrv_refresh_filename(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_nb_sectors(BlockDriverState *bs);
|
||||||
int64_t bdrv_getlength(BlockDriverState *bs);
|
int64_t bdrv_getlength(BlockDriverState *bs);
|
||||||
int64_t bdrv_get_allocated_file_size(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);
|
int coroutine_fn (*bdrv_co_flush_to_os)(BlockDriverState *bs);
|
||||||
|
|
||||||
const char *protocol_name;
|
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);
|
int64_t (*bdrv_getlength)(BlockDriverState *bs);
|
||||||
bool has_variable_length;
|
bool has_variable_length;
|
||||||
|
@ -252,7 +252,7 @@ struct BlockDriver {
|
||||||
* Returns 0 for completed check, -errno for internal errors.
|
* Returns 0 for completed check, -errno for internal errors.
|
||||||
* The check results are stored in result.
|
* The check results are stored in result.
|
||||||
*/
|
*/
|
||||||
int (*bdrv_check)(BlockDriverState* bs, BdrvCheckResult *result,
|
int (*bdrv_check)(BlockDriverState *bs, BdrvCheckResult *result,
|
||||||
BdrvCheckMode fix);
|
BdrvCheckMode fix);
|
||||||
|
|
||||||
int (*bdrv_amend_options)(BlockDriverState *bs, QemuOpts *opts,
|
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
|
/* 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
|
* node name for identifying the node in question (in particular, a BB
|
||||||
* name), or NULL if the parent can't provide a better name. */
|
* 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
|
/* 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
|
* 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
|
* QOM path of the device owning the BlockBackend, job type and ID etc. The
|
||||||
* caller is responsible for freeing the memory. */
|
* 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
|
* 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 count, BdrvRequestFlags flags);
|
||||||
int blk_pwrite_compressed(BlockBackend *blk, int64_t offset, const void *buf,
|
int blk_pwrite_compressed(BlockBackend *blk, int64_t offset, const void *buf,
|
||||||
int count);
|
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_pdiscard(BlockBackend *blk, int64_t offset, int count);
|
||||||
int blk_save_vmstate(BlockBackend *blk, const uint8_t *buf,
|
int blk_save_vmstate(BlockBackend *blk, const uint8_t *buf,
|
||||||
int64_t pos, int size);
|
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) {
|
if (s->sector_next_status <= sector_num) {
|
||||||
BlockDriverState *file;
|
BlockDriverState *file;
|
||||||
ret = bdrv_get_block_status(blk_bs(s->src[src_cur]),
|
if (s->target_has_backing) {
|
||||||
sector_num - src_cur_offset,
|
ret = bdrv_get_block_status(blk_bs(s->src[src_cur]),
|
||||||
n, &n, &file);
|
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) {
|
if (ret < 0) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -1565,26 +1571,8 @@ static int convert_iteration_sectors(ImgConvertState *s, int64_t sector_num)
|
||||||
s->status = BLK_ZERO;
|
s->status = BLK_ZERO;
|
||||||
} else if (ret & BDRV_BLOCK_DATA) {
|
} else if (ret & BDRV_BLOCK_DATA) {
|
||||||
s->status = BLK_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 {
|
} else {
|
||||||
s->status = BLK_BACKING_FILE;
|
s->status = s->target_has_backing ? BLK_BACKING_FILE : BLK_DATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
s->sector_next_status = sector_num + n;
|
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) {
|
while (nb_sectors > 0) {
|
||||||
int n = nb_sectors;
|
int n = nb_sectors;
|
||||||
|
BdrvRequestFlags flags = s->compressed ? BDRV_REQ_WRITE_COMPRESSED : 0;
|
||||||
|
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case BLK_BACKING_FILE:
|
case BLK_BACKING_FILE:
|
||||||
/* If we have a backing file, leave clusters unallocated that are
|
/* 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;
|
break;
|
||||||
|
|
||||||
case BLK_DATA:
|
case BLK_DATA:
|
||||||
/* We must always write compressed clusters as a whole, so don't
|
/* If we're told to keep the target fully allocated (-S 0) or there
|
||||||
* try to find zeroed parts in the buffer. We can only save the
|
* is real non-zero data, we must write it. Otherwise we can treat
|
||||||
* write if the buffer is completely zeroed and we're allowed to
|
* it as zero sectors.
|
||||||
* keep the target sparse. */
|
* Compressed clusters need to be written as a whole, so in that
|
||||||
if (s->compressed) {
|
* case we can only save the write if the buffer is completely
|
||||||
if (s->has_zero_init && s->min_sparse &&
|
* zeroed. */
|
||||||
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 (!s->min_sparse ||
|
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_base = buf;
|
||||||
iov.iov_len = n << BDRV_SECTOR_BITS;
|
iov.iov_len = n << BDRV_SECTOR_BITS;
|
||||||
qemu_iovec_init_external(&qiov, &iov, 1);
|
qemu_iovec_init_external(&qiov, &iov, 1);
|
||||||
|
|
||||||
ret = blk_co_pwritev(s->target, sector_num << BDRV_SECTOR_BITS,
|
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) {
|
if (ret < 0) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -1716,6 +1687,7 @@ static int coroutine_fn convert_co_write(ImgConvertState *s, int64_t sector_num,
|
||||||
|
|
||||||
case BLK_ZERO:
|
case BLK_ZERO:
|
||||||
if (s->has_zero_init) {
|
if (s->has_zero_init) {
|
||||||
|
assert(!s->target_has_backing);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
ret = blk_co_pwrite_zeroes(s->target,
|
ret = blk_co_pwrite_zeroes(s->target,
|
||||||
|
@ -3464,20 +3436,11 @@ static int img_resize(int argc, char **argv)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = blk_truncate(blk, total_size);
|
ret = blk_truncate(blk, total_size, &err);
|
||||||
switch (ret) {
|
if (!ret) {
|
||||||
case 0:
|
|
||||||
qprintf(quiet, "Image resized.\n");
|
qprintf(quiet, "Image resized.\n");
|
||||||
break;
|
} else {
|
||||||
case -ENOTSUP:
|
error_report_err(err);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
out:
|
out:
|
||||||
blk_unref(blk);
|
blk_unref(blk);
|
||||||
|
|
|
@ -84,7 +84,8 @@ with or without a command shows help and lists the supported formats
|
||||||
@item -p
|
@item -p
|
||||||
display progress bar (compare, convert and rebase commands only).
|
display progress bar (compare, convert and rebase commands only).
|
||||||
If the @var{-p} option is not used for a command that supports it, the
|
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
|
@item -q
|
||||||
Quiet mode - do not print any output (except errors). There's no progress bar
|
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.
|
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)
|
static int truncate_f(BlockBackend *blk, int argc, char **argv)
|
||||||
{
|
{
|
||||||
|
Error *local_err = NULL;
|
||||||
int64_t offset;
|
int64_t offset;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
@ -1576,9 +1577,9 @@ static int truncate_f(BlockBackend *blk, int argc, char **argv)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = blk_truncate(blk, offset);
|
ret = blk_truncate(blk, offset, &local_err);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
printf("truncate: %s\n", strerror(-ret));
|
error_report_err(local_err);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,16 +42,18 @@ _supported_fmt qcow2
|
||||||
_supported_proto generic
|
_supported_proto generic
|
||||||
_supported_os Linux
|
_supported_os Linux
|
||||||
|
|
||||||
|
# Intentionally create an unaligned image
|
||||||
IMGOPTS="compat=1.1"
|
IMGOPTS="compat=1.1"
|
||||||
IMG_SIZE=64M
|
IMG_SIZE=$((64 * 1024 * 1024 + 512))
|
||||||
|
|
||||||
echo
|
echo
|
||||||
echo "=== Testing snapshotting an image with zero clusters ==="
|
echo "=== Testing cluster discards ==="
|
||||||
echo
|
echo
|
||||||
_make_test_img $IMG_SIZE
|
_make_test_img $IMG_SIZE
|
||||||
# Write some normal clusters, zero them (creating preallocated zero clusters)
|
# Write some normal clusters, zero some of them (creating preallocated
|
||||||
# and discard those
|
# zero clusters) and discard everything. Everything should now read as 0.
|
||||||
$QEMU_IO -c "write 0 256k" -c "write -z 0 256k" -c "discard 0 256k" "$TEST_IMG" \
|
$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
|
| _filter_qemu_io
|
||||||
# Check the image (there shouldn't be any leaks)
|
# Check the image (there shouldn't be any leaks)
|
||||||
_check_test_img
|
_check_test_img
|
||||||
|
|
|
@ -1,13 +1,17 @@
|
||||||
QA output created by 066
|
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
|
wrote 262144/262144 bytes at offset 0
|
||||||
256 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
256 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||||
wrote 262144/262144 bytes at offset 0
|
wrote 262144/262144 bytes at offset 0
|
||||||
256 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
256 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||||
discard 262144/262144 bytes at offset 0
|
wrote 512/512 bytes at offset 67108864
|
||||||
256 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
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.
|
No errors were found on the image.
|
||||||
*** done
|
*** done
|
||||||
|
|
|
@ -86,7 +86,8 @@ s/ .*//p
|
||||||
elif $xgroup
|
elif $xgroup
|
||||||
then
|
then
|
||||||
# arg after -x
|
# 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 /"'{
|
group_list=`sed -n <"$source_iotests/group" -e 's/$/ /' -e "/^[0-9][0-9][0-9].* $r /"'{
|
||||||
s/ .*//p
|
s/ .*//p
|
||||||
}'`
|
}'`
|
||||||
|
@ -138,7 +139,7 @@ common options
|
||||||
-v verbose
|
-v verbose
|
||||||
-d debug
|
-d debug
|
||||||
|
|
||||||
check options
|
image format options
|
||||||
-raw test raw (default)
|
-raw test raw (default)
|
||||||
-bochs test bochs
|
-bochs test bochs
|
||||||
-cloop test cloop
|
-cloop test cloop
|
||||||
|
@ -150,14 +151,18 @@ check options
|
||||||
-vpc test vpc
|
-vpc test vpc
|
||||||
-vhdx test vhdx
|
-vhdx test vhdx
|
||||||
-vmdk test vmdk
|
-vmdk test vmdk
|
||||||
|
-luks test luks
|
||||||
|
|
||||||
|
image protocol options
|
||||||
-file test file (default)
|
-file test file (default)
|
||||||
-rbd test rbd
|
-rbd test rbd
|
||||||
-sheepdog test sheepdog
|
-sheepdog test sheepdog
|
||||||
-nbd test nbd
|
-nbd test nbd
|
||||||
-ssh test ssh
|
-ssh test ssh
|
||||||
-nfs test nfs
|
-nfs test nfs
|
||||||
-luks test luks
|
|
||||||
-vxhs test vxhs
|
-vxhs test vxhs
|
||||||
|
|
||||||
|
other options
|
||||||
-xdiff graphical mode diff
|
-xdiff graphical mode diff
|
||||||
-nocache use O_DIRECT on backing file
|
-nocache use O_DIRECT on backing file
|
||||||
-misalign misalign memory allocations
|
-misalign misalign memory allocations
|
||||||
|
|
|
@ -88,6 +88,9 @@ static void progress_dummy_init(void)
|
||||||
action.sa_handler = sigusr_print;
|
action.sa_handler = sigusr_print;
|
||||||
action.sa_flags = 0;
|
action.sa_flags = 0;
|
||||||
sigaction(SIGUSR1, &action, NULL);
|
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
|
* SIGUSR1 is SIG_IPI and gets blocked in qemu_init_main_loop(). In the
|
||||||
|
|
Loading…
Reference in New Issue