block: Add errp to b{lk,drv}_truncate()

For one thing, this allows us to drop the error message generation from
qemu-img.c and blockdev.c and instead have it unified in
bdrv_truncate().

Signed-off-by: Max Reitz <mreitz@redhat.com>
Message-id: 20170328205129.15138-3-mreitz@redhat.com
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Max Reitz <mreitz@redhat.com>
This commit is contained in:
Max Reitz 2017-03-28 22:51:27 +02:00
parent 55b9392b98
commit ed3d2ec98a
22 changed files with 73 additions and 90 deletions

16
block.c
View File

@ -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,12 +3315,18 @@ 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); ret = drv->bdrv_truncate(bs, offset);
if (ret == 0) { if (ret == 0) {
@ -3328,6 +3334,8 @@ int bdrv_truncate(BdrvChild *child, int64_t offset)
bdrv_dirty_bitmap_truncate(bs); bdrv_dirty_bitmap_truncate(bs);
bdrv_parent_cb_resize(bs); bdrv_parent_cb_resize(bs);
++bs->write_gen; ++bs->write_gen;
} else {
error_setg_errno(errp, -ret, "Failed to resize image");
} }
return ret; return ret;
} }

View File

@ -661,7 +661,7 @@ static int64_t blkdebug_getlength(BlockDriverState *bs)
static int blkdebug_truncate(BlockDriverState *bs, int64_t offset) static int blkdebug_truncate(BlockDriverState *bs, int64_t offset)
{ {
return bdrv_truncate(bs->file, offset); return bdrv_truncate(bs->file, offset, NULL);
} }
static void blkdebug_refresh_filename(BlockDriverState *bs, QDict *options) static void blkdebug_refresh_filename(BlockDriverState *bs, QDict *options)

View File

@ -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)

View File

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

View File

@ -389,7 +389,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, NULL);
} }
static void block_crypto_close(BlockDriverState *bs) static void block_crypto_close(BlockDriverState *bs)

View File

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

View File

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

View File

@ -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;

View File

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

View File

@ -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;
} }
@ -2584,7 +2584,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 +2674,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 +2799,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 +3276,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;
} }
} }

View File

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

View File

@ -341,7 +341,7 @@ static int raw_truncate(BlockDriverState *bs, int64_t offset)
s->size = offset; s->size = offset;
offset += s->offset; offset += s->offset;
return bdrv_truncate(bs->file, offset); return bdrv_truncate(bs->file, offset, NULL);
} }
static int raw_media_changed(BlockDriverState *bs) static int raw_media_changed(BlockDriverState *bs)

View File

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

View File

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

View File

@ -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);
} }
/* /*
@ -1607,17 +1607,13 @@ 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) {
error_setg_errno(errp, -ret,
"Failed to resize the underlying file");
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) {
error_setg_errno(errp, -ret,
"Failed to resize the underlying file");
goto exit; goto exit;
} }
} else { } else {

View File

@ -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) {

View File

@ -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:

View File

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

View File

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

View File

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

View File

@ -3464,20 +3464,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);

View File

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