mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Merge remote-tracking branch 'kwolf/tags/for-upstream' into staging
Block layer patches # gpg: Signature made Fri 28 Apr 2017 09:20:17 PM BST # gpg: using RSA key 0x7F09B272C88F2FD6 # gpg: Good signature from "Kevin Wolf <kwolf@redhat.com>" # Primary key fingerprint: DC3D EB15 9A9A F95D 3D74 56FE 7F09 B272 C88F 2FD6 * kwolf/tags/for-upstream: (34 commits) 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 qemu-img: Document backing options qemu-img/convert: Move bs_n > 1 && -B check down qemu-img/convert: Use @opts for one thing only block: fix alignment calculations in bdrv_co_do_zero_pwritev block: Do not unref bs->file on error in BD's open iotests: 109: Filter out "len" of failed jobs iotests: Fix typo in 026 Issue a deprecation warning if the user specifies the "-hdachs" option. ... Message-id: 1493411622-5343-1-git-send-email-kwolf@redhat.com Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
@@ -1204,7 +1204,7 @@ static int bdrv_open_common(BlockDriverState *bs, BlockBackend *file,
|
||||
filename = qdict_get_try_str(options, "filename");
|
||||
}
|
||||
|
||||
if (drv->bdrv_needs_filename && !filename) {
|
||||
if (drv->bdrv_needs_filename && (!filename || !filename[0])) {
|
||||
error_setg(errp, "The '%s' block driver requires a file name",
|
||||
drv->format_name);
|
||||
ret = -EINVAL;
|
||||
@@ -3307,26 +3307,30 @@ 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;
|
||||
int ret;
|
||||
|
||||
/* FIXME: Some format block drivers use this function instead of implicitly
|
||||
* growing their file by writing beyond its end.
|
||||
* See bdrv_aligned_pwritev() for an explanation why we currently
|
||||
* cannot assert this permission in that case. */
|
||||
// assert(child->perm & BLK_PERM_RESIZE);
|
||||
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);
|
||||
|
||||
+3
-5
@@ -389,14 +389,12 @@ static int blkdebug_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
} else if (align) {
|
||||
error_setg(errp, "Invalid alignment");
|
||||
ret = -EINVAL;
|
||||
goto fail_unref;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
goto out;
|
||||
|
||||
fail_unref:
|
||||
bdrv_unref_child(bs, bs->file);
|
||||
out:
|
||||
if (ret < 0) {
|
||||
g_free(s->config_file);
|
||||
@@ -661,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)
|
||||
|
||||
@@ -37,9 +37,6 @@ static int blkreplay_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
|
||||
ret = 0;
|
||||
fail:
|
||||
if (ret < 0) {
|
||||
bdrv_unref_child(bs, bs->file);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -142,9 +142,6 @@ static int blkverify_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
|
||||
ret = 0;
|
||||
fail:
|
||||
if (ret < 0) {
|
||||
bdrv_unref_child(bs, bs->file);
|
||||
}
|
||||
qemu_opts_del(opts);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -420,7 +420,7 @@ void monitor_remove_blk(BlockBackend *blk)
|
||||
* Return @blk's name, a non-null string.
|
||||
* Returns an empty string iff @blk is not referenced by the monitor.
|
||||
*/
|
||||
const char *blk_name(BlockBackend *blk)
|
||||
const char *blk_name(const BlockBackend *blk)
|
||||
{
|
||||
return blk->name ?: "";
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
+3
-2
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
+3
-2
@@ -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)
|
||||
|
||||
+13
-8
@@ -25,8 +25,6 @@
|
||||
#include "qapi/error.h"
|
||||
#include "qemu/cutils.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "qemu/timer.h"
|
||||
#include "qemu/log.h"
|
||||
#include "block/block_int.h"
|
||||
#include "qemu/module.h"
|
||||
#include "trace.h"
|
||||
@@ -1409,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;
|
||||
}
|
||||
|
||||
|
||||
+3
-4
@@ -24,7 +24,6 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qemu/cutils.h"
|
||||
#include "qemu/timer.h"
|
||||
#include "block/block_int.h"
|
||||
#include "qemu/module.h"
|
||||
#include "block/raw-aio.h"
|
||||
@@ -461,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;
|
||||
@@ -476,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;
|
||||
|
||||
+5
-2
@@ -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;
|
||||
|
||||
+4
-12
@@ -1362,16 +1362,8 @@ static int coroutine_fn bdrv_aligned_pwritev(BdrvChild *child,
|
||||
assert(!waited || !req->serialising);
|
||||
assert(req->overlap_offset <= offset);
|
||||
assert(offset + bytes <= req->overlap_offset + req->overlap_bytes);
|
||||
/* FIXME: Block migration uses the BlockBackend of the guest device at a
|
||||
* point when it has not yet taken write permissions. This will be
|
||||
* fixed by a future patch, but for now we have to bypass this
|
||||
* assertion for block migration to work. */
|
||||
// assert(child->perm & BLK_PERM_WRITE);
|
||||
/* FIXME: Because of the above, we also cannot guarantee that all format
|
||||
* BDS take the BLK_PERM_RESIZE permission on their file BDS, since
|
||||
* they are not obligated to do so if they do not have any parent
|
||||
* that has taken the permission to write to them. */
|
||||
// assert(end_sector <= bs->total_sectors || child->perm & BLK_PERM_RESIZE);
|
||||
assert(child->perm & BLK_PERM_WRITE);
|
||||
assert(end_sector <= bs->total_sectors || child->perm & BLK_PERM_RESIZE);
|
||||
|
||||
ret = notifier_with_return_list_notify(&bs->before_write_notifiers, req);
|
||||
|
||||
@@ -1452,7 +1444,7 @@ static int coroutine_fn bdrv_co_do_zero_pwritev(BdrvChild *child,
|
||||
int ret = 0;
|
||||
|
||||
head_padding_bytes = offset & (align - 1);
|
||||
tail_padding_bytes = align - ((offset + bytes) & (align - 1));
|
||||
tail_padding_bytes = (align - (offset + bytes)) & (align - 1);
|
||||
|
||||
|
||||
assert(flags & BDRV_REQ_ZERO_WRITE);
|
||||
@@ -2308,7 +2300,7 @@ int coroutine_fn bdrv_co_flush(BlockDriverState *bs)
|
||||
|
||||
bdrv_inc_in_flight(bs);
|
||||
|
||||
if (!bs || !bdrv_is_inserted(bs) || bdrv_is_read_only(bs) ||
|
||||
if (!bdrv_is_inserted(bs) || bdrv_is_read_only(bs) ||
|
||||
bdrv_is_sg(bs)) {
|
||||
goto early_exit;
|
||||
}
|
||||
|
||||
+4
-2
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -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;
|
||||
}
|
||||
|
||||
+10
-2
@@ -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
|
||||
|
||||
+8
-5
@@ -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);
|
||||
|
||||
+3
-3
@@ -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);
|
||||
|
||||
+21
-10
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
+5
-3
@@ -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;
|
||||
}
|
||||
|
||||
+4
-2
@@ -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)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user