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

Block layer patches:

- Fix resize (extending) of short overlays
- nvme: introduce PMR support from NVMe 1.4 spec
- qemu-storage-daemon: Fix non-string --object properties

# gpg: Signature made Thu 30 Apr 2020 16:51:45 BST
# gpg:                using RSA key DC3DEB159A9AF95D3D7456FE7F09B272C88F2FD6
# gpg:                issuer "kwolf@redhat.com"
# gpg: Good signature from "Kevin Wolf <kwolf@redhat.com>" [full]
# Primary key fingerprint: DC3D EB15 9A9A F95D 3D74  56FE 7F09 B272 C88F 2FD6

* remotes/kevin/tags/for-upstream:
  qemu-storage-daemon: Fix non-string --object properties
  qom: Factor out user_creatable_add_dict()
  nvme: introduce PMR support from NVMe 1.4 spec
  qcow2: Forward ZERO_WRITE flag for full preallocation
  iotests: Test committing to short backing file
  iotests: Filter testfiles out in filter_img_info()
  block: truncate: Don't make backing file data visible
  file-posix: Support BDRV_REQ_ZERO_WRITE for truncate
  raw-format: Support BDRV_REQ_ZERO_WRITE for truncate
  qcow2: Support BDRV_REQ_ZERO_WRITE for truncate
  block-backend: Add flags to blk_truncate()
  block: Add flags to bdrv(_co)_truncate()
  block: Add flags to BlockDriver.bdrv_co_truncate()
  qemu-iotests: allow qcow2 external discarded clusters to contain stale data
  qcow2: Add incompatibility note between backing files and raw external data files

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell
2020-04-30 19:25:41 +01:00
49 changed files with 951 additions and 96 deletions
+2 -1
View File
@@ -548,7 +548,8 @@ static int64_t create_file_fallback_truncate(BlockBackend *blk,
int64_t size;
int ret;
ret = blk_truncate(blk, minimum_size, false, PREALLOC_MODE_OFF, &local_err);
ret = blk_truncate(blk, minimum_size, false, PREALLOC_MODE_OFF, 0,
&local_err);
if (ret < 0 && ret != -ENOTSUP) {
error_propagate(errp, local_err);
return ret;
+2 -2
View File
@@ -2137,14 +2137,14 @@ int blk_pwrite_compressed(BlockBackend *blk, int64_t offset, const void *buf,
}
int blk_truncate(BlockBackend *blk, int64_t offset, bool exact,
PreallocMode prealloc, Error **errp)
PreallocMode prealloc, BdrvRequestFlags flags, Error **errp)
{
if (!blk_is_available(blk)) {
error_setg(errp, "No medium inserted");
return -ENOMEDIUM;
}
return bdrv_truncate(blk->root, offset, exact, prealloc, errp);
return bdrv_truncate(blk->root, offset, exact, prealloc, flags, errp);
}
int blk_save_vmstate(BlockBackend *blk, const uint8_t *buf,
+2 -2
View File
@@ -133,7 +133,7 @@ static int coroutine_fn commit_run(Job *job, Error **errp)
}
if (base_len < len) {
ret = blk_truncate(s->base, len, false, PREALLOC_MODE_OFF, NULL);
ret = blk_truncate(s->base, len, false, PREALLOC_MODE_OFF, 0, NULL);
if (ret) {
goto out;
}
@@ -458,7 +458,7 @@ 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, false, PREALLOC_MODE_OFF,
ret = blk_truncate(backing, length, false, PREALLOC_MODE_OFF, 0,
&local_err);
if (ret < 0) {
error_report_err(local_err);
+4 -3
View File
@@ -115,7 +115,7 @@ static ssize_t block_crypto_init_func(QCryptoBlock *block,
* which will be used by the crypto header
*/
return blk_truncate(data->blk, data->size + headerlen, false,
data->prealloc, errp);
data->prealloc, 0, errp);
}
@@ -299,7 +299,8 @@ static int block_crypto_co_create_generic(BlockDriverState *bs,
static int coroutine_fn
block_crypto_co_truncate(BlockDriverState *bs, int64_t offset, bool exact,
PreallocMode prealloc, Error **errp)
PreallocMode prealloc, BdrvRequestFlags flags,
Error **errp)
{
BlockCrypto *crypto = bs->opaque;
uint64_t payload_offset =
@@ -312,7 +313,7 @@ block_crypto_co_truncate(BlockDriverState *bs, int64_t offset, bool exact,
offset += payload_offset;
return bdrv_co_truncate(bs->file, offset, exact, prealloc, errp);
return bdrv_co_truncate(bs->file, offset, exact, prealloc, 0, errp);
}
static void block_crypto_close(BlockDriverState *bs)
+5 -1
View File
@@ -702,6 +702,10 @@ static int raw_open_common(BlockDriverState *bs, QDict *options,
#endif
bs->supported_zero_flags = BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK;
if (S_ISREG(st.st_mode)) {
/* When extending regular files, we get zeros from the OS */
bs->supported_truncate_flags = BDRV_REQ_ZERO_WRITE;
}
ret = 0;
fail:
if (filename && (bdrv_flags & BDRV_O_TEMPORARY)) {
@@ -2080,7 +2084,7 @@ raw_regular_truncate(BlockDriverState *bs, int fd, int64_t offset,
static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset,
bool exact, PreallocMode prealloc,
Error **errp)
BdrvRequestFlags flags, Error **errp)
{
BDRVRawState *s = bs->opaque;
struct stat st;
+1 -1
View File
@@ -469,7 +469,7 @@ static void raw_close(BlockDriverState *bs)
static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset,
bool exact, PreallocMode prealloc,
Error **errp)
BdrvRequestFlags flags, Error **errp)
{
BDRVRawState *s = bs->opaque;
LONG low, high;
+1
View File
@@ -1228,6 +1228,7 @@ static coroutine_fn int qemu_gluster_co_truncate(BlockDriverState *bs,
int64_t offset,
bool exact,
PreallocMode prealloc,
BdrvRequestFlags flags,
Error **errp)
{
BDRVGlusterState *s = bs->opaque;
+38 -5
View File
@@ -3339,7 +3339,8 @@ static void bdrv_parent_cb_resize(BlockDriverState *bs)
* 'offset' bytes in length.
*/
int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
PreallocMode prealloc, Error **errp)
PreallocMode prealloc, BdrvRequestFlags flags,
Error **errp)
{
BlockDriverState *bs = child->bs;
BlockDriver *drv = bs->drv;
@@ -3393,10 +3394,40 @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
goto out;
}
/*
* If the image has a backing file that is large enough that it would
* provide data for the new area, we cannot leave it unallocated because
* then the backing file content would become visible. Instead, zero-fill
* the new area.
*
* Note that if the image has a backing file, but was opened without the
* backing file, taking care of keeping things consistent with that backing
* file is the user's responsibility.
*/
if (new_bytes && bs->backing) {
int64_t backing_len;
backing_len = bdrv_getlength(backing_bs(bs));
if (backing_len < 0) {
ret = backing_len;
error_setg_errno(errp, -ret, "Could not get backing file size");
goto out;
}
if (backing_len > old_size) {
flags |= BDRV_REQ_ZERO_WRITE;
}
}
if (drv->bdrv_co_truncate) {
ret = drv->bdrv_co_truncate(bs, offset, exact, prealloc, errp);
if (flags & ~bs->supported_truncate_flags) {
error_setg(errp, "Block driver does not support requested flags");
ret = -ENOTSUP;
goto out;
}
ret = drv->bdrv_co_truncate(bs, offset, exact, prealloc, flags, errp);
} else if (bs->file && drv->is_filter) {
ret = bdrv_co_truncate(bs->file, offset, exact, prealloc, errp);
ret = bdrv_co_truncate(bs->file, offset, exact, prealloc, flags, errp);
} else {
error_setg(errp, "Image format driver does not support resize");
ret = -ENOTSUP;
@@ -3429,6 +3460,7 @@ typedef struct TruncateCo {
int64_t offset;
bool exact;
PreallocMode prealloc;
BdrvRequestFlags flags;
Error **errp;
int ret;
} TruncateCo;
@@ -3437,12 +3469,12 @@ static void coroutine_fn bdrv_truncate_co_entry(void *opaque)
{
TruncateCo *tco = opaque;
tco->ret = bdrv_co_truncate(tco->child, tco->offset, tco->exact,
tco->prealloc, tco->errp);
tco->prealloc, tco->flags, tco->errp);
aio_wait_kick();
}
int bdrv_truncate(BdrvChild *child, int64_t offset, bool exact,
PreallocMode prealloc, Error **errp)
PreallocMode prealloc, BdrvRequestFlags flags, Error **errp)
{
Coroutine *co;
TruncateCo tco = {
@@ -3450,6 +3482,7 @@ int bdrv_truncate(BdrvChild *child, int64_t offset, bool exact,
.offset = offset,
.exact = exact,
.prealloc = prealloc,
.flags = flags,
.errp = errp,
.ret = NOT_DONE,
};
+1 -1
View File
@@ -2124,7 +2124,7 @@ static void iscsi_reopen_commit(BDRVReopenState *reopen_state)
static int coroutine_fn iscsi_co_truncate(BlockDriverState *bs, int64_t offset,
bool exact, PreallocMode prealloc,
Error **errp)
BdrvRequestFlags flags, Error **errp)
{
IscsiLun *iscsilun = bs->opaque;
int64_t cur_length;
+1 -1
View File
@@ -900,7 +900,7 @@ static int coroutine_fn mirror_run(Job *job, Error **errp)
if (s->bdev_length > base_length) {
ret = blk_truncate(s->target, s->bdev_length, false,
PREALLOC_MODE_OFF, NULL);
PREALLOC_MODE_OFF, 0, NULL);
if (ret < 0) {
goto immediate_exit;
}
+2 -1
View File
@@ -755,7 +755,8 @@ static int64_t nfs_get_allocated_file_size(BlockDriverState *bs)
static int coroutine_fn
nfs_file_co_truncate(BlockDriverState *bs, int64_t offset, bool exact,
PreallocMode prealloc, Error **errp)
PreallocMode prealloc, BdrvRequestFlags flags,
Error **errp)
{
NFSClient *client = bs->opaque;
int ret;
+3 -3
View File
@@ -203,7 +203,7 @@ static int64_t allocate_clusters(BlockDriverState *bs, int64_t sector_num,
} else {
ret = bdrv_truncate(bs->file,
(s->data_end + space) << BDRV_SECTOR_BITS,
false, PREALLOC_MODE_OFF, NULL);
false, PREALLOC_MODE_OFF, 0, NULL);
}
if (ret < 0) {
return ret;
@@ -493,7 +493,7 @@ static int coroutine_fn parallels_co_check(BlockDriverState *bs,
* That means we have to pass exact=true.
*/
ret = bdrv_truncate(bs->file, res->image_end_offset, true,
PREALLOC_MODE_OFF, &local_err);
PREALLOC_MODE_OFF, 0, &local_err);
if (ret < 0) {
error_report_err(local_err);
res->check_errors++;
@@ -889,7 +889,7 @@ static void parallels_close(BlockDriverState *bs)
/* errors are ignored, so we might as well pass exact=true */
bdrv_truncate(bs->file, s->data_end << BDRV_SECTOR_BITS, true,
PREALLOC_MODE_OFF, NULL);
PREALLOC_MODE_OFF, 0, NULL);
}
g_free(s->bat_dirty_bmap);
+2 -2
View File
@@ -480,7 +480,7 @@ static int get_cluster_offset(BlockDriverState *bs,
return -E2BIG;
}
ret = bdrv_truncate(bs->file, cluster_offset + s->cluster_size,
false, PREALLOC_MODE_OFF, NULL);
false, PREALLOC_MODE_OFF, 0, NULL);
if (ret < 0) {
return ret;
}
@@ -1035,7 +1035,7 @@ static int qcow_make_empty(BlockDriverState *bs)
l1_length) < 0)
return -1;
ret = bdrv_truncate(bs->file, s->l1_table_offset + l1_length, false,
PREALLOC_MODE_OFF, NULL);
PREALLOC_MODE_OFF, 0, NULL);
if (ret < 0)
return ret;
+1 -1
View File
@@ -1795,7 +1795,7 @@ int qcow2_cluster_zeroize(BlockDriverState *bs, uint64_t offset,
/* Caller must pass aligned values, except at image end */
assert(QEMU_IS_ALIGNED(offset, s->cluster_size));
assert(QEMU_IS_ALIGNED(end_offset, s->cluster_size) ||
end_offset == bs->total_sectors << BDRV_SECTOR_BITS);
end_offset >= bs->total_sectors << BDRV_SECTOR_BITS);
/* The zero flag is only supported by version 3 and newer */
if (s->qcow_version < 3) {
+1 -1
View File
@@ -2018,7 +2018,7 @@ static int check_refblocks(BlockDriverState *bs, BdrvCheckResult *res,
}
ret = bdrv_truncate(bs->file, offset + s->cluster_size, false,
PREALLOC_MODE_OFF, &local_err);
PREALLOC_MODE_OFF, 0, &local_err);
if (ret < 0) {
error_report_err(local_err);
goto resize_fail;
+63 -10
View File
@@ -1726,6 +1726,7 @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
bs->supported_zero_flags = header.version >= 3 ?
BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK : 0;
bs->supported_truncate_flags = BDRV_REQ_ZERO_WRITE;
/* Repair image if dirty */
if (!(flags & (BDRV_O_CHECK | BDRV_O_INACTIVE)) && !bs->read_only &&
@@ -3095,7 +3096,7 @@ static int coroutine_fn preallocate_co(BlockDriverState *bs, uint64_t offset,
mode = PREALLOC_MODE_OFF;
}
ret = bdrv_co_truncate(s->data_file, host_offset + cur_bytes, false,
mode, errp);
mode, 0, errp);
if (ret < 0) {
return ret;
}
@@ -3511,7 +3512,7 @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp)
/* Okay, now that we have a valid image, let's give it the right size */
ret = blk_truncate(blk, qcow2_opts->size, false, qcow2_opts->preallocation,
errp);
0, errp);
if (ret < 0) {
error_prepend(errp, "Could not resize image: ");
goto out;
@@ -3964,7 +3965,7 @@ fail:
static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
bool exact, PreallocMode prealloc,
Error **errp)
BdrvRequestFlags flags, Error **errp)
{
BDRVQcow2State *s = bs->opaque;
uint64_t old_length;
@@ -4061,7 +4062,7 @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
* always fulfilled, so there is no need to pass it on.)
*/
bdrv_co_truncate(bs->file, (last_cluster + 1) * s->cluster_size,
false, PREALLOC_MODE_OFF, &local_err);
false, PREALLOC_MODE_OFF, 0, &local_err);
if (local_err) {
warn_reportf_err(local_err,
"Failed to truncate the tail of the image: ");
@@ -4083,7 +4084,8 @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
* file should be resized to the exact target size, too,
* so we pass @exact here.
*/
ret = bdrv_co_truncate(s->data_file, offset, exact, prealloc, errp);
ret = bdrv_co_truncate(s->data_file, offset, exact, prealloc, 0,
errp);
if (ret < 0) {
goto fail;
}
@@ -4168,8 +4170,25 @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
/* Allocate the data area */
new_file_size = allocation_start +
nb_new_data_clusters * s->cluster_size;
/* Image file grows, so @exact does not matter */
ret = bdrv_co_truncate(bs->file, new_file_size, false, prealloc, errp);
/*
* Image file grows, so @exact does not matter.
*
* If we need to zero out the new area, try first whether the protocol
* driver can already take care of this.
*/
if (flags & BDRV_REQ_ZERO_WRITE) {
ret = bdrv_co_truncate(bs->file, new_file_size, false, prealloc,
BDRV_REQ_ZERO_WRITE, NULL);
if (ret >= 0) {
flags &= ~BDRV_REQ_ZERO_WRITE;
}
} else {
ret = -1;
}
if (ret < 0) {
ret = bdrv_co_truncate(bs->file, new_file_size, false, prealloc, 0,
errp);
}
if (ret < 0) {
error_prepend(errp, "Failed to resize underlying file: ");
qcow2_free_clusters(bs, allocation_start,
@@ -4212,6 +4231,39 @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
g_assert_not_reached();
}
if ((flags & BDRV_REQ_ZERO_WRITE) && offset > old_length) {
uint64_t zero_start = QEMU_ALIGN_UP(old_length, s->cluster_size);
/*
* Use zero clusters as much as we can. qcow2_cluster_zeroize()
* requires a cluster-aligned start. The end may be unaligned if it is
* at the end of the image (which it is here).
*/
ret = qcow2_cluster_zeroize(bs, zero_start, offset - zero_start, 0);
if (ret < 0) {
error_setg_errno(errp, -ret, "Failed to zero out new clusters");
goto fail;
}
/* Write explicit zeros for the unaligned head */
if (zero_start > old_length) {
uint64_t len = zero_start - old_length;
uint8_t *buf = qemu_blockalign0(bs, len);
QEMUIOVector qiov;
qemu_iovec_init_buf(&qiov, buf, len);
qemu_co_mutex_unlock(&s->lock);
ret = qcow2_co_pwritev_part(bs, old_length, len, &qiov, 0, 0);
qemu_co_mutex_lock(&s->lock);
qemu_vfree(buf);
if (ret < 0) {
error_setg_errno(errp, -ret, "Failed to zero out the new area");
goto fail;
}
}
}
if (prealloc != PREALLOC_MODE_OFF) {
/* Flush metadata before actually changing the image size */
ret = qcow2_write_caches(bs);
@@ -4348,7 +4400,8 @@ qcow2_co_pwritev_compressed_part(BlockDriverState *bs,
if (len < 0) {
return len;
}
return bdrv_co_truncate(bs->file, len, false, PREALLOC_MODE_OFF, NULL);
return bdrv_co_truncate(bs->file, len, false, PREALLOC_MODE_OFF, 0,
NULL);
}
if (offset_into_cluster(s, offset)) {
@@ -4563,7 +4616,7 @@ static int make_completely_empty(BlockDriverState *bs)
}
ret = bdrv_truncate(bs->file, (3 + l1_clusters) * s->cluster_size, false,
PREALLOC_MODE_OFF, &local_err);
PREALLOC_MODE_OFF, 0, &local_err);
if (ret < 0) {
error_report_err(local_err);
goto fail;
@@ -5371,7 +5424,7 @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts,
* Amending image options should ensure that the image has
* exactly the given new values, so pass exact=true here.
*/
ret = blk_truncate(blk, new_size, true, PREALLOC_MODE_OFF, errp);
ret = blk_truncate(blk, new_size, true, PREALLOC_MODE_OFF, 0, errp);
blk_unref(blk);
if (ret < 0) {
return ret;
+2 -1
View File
@@ -677,7 +677,7 @@ static int coroutine_fn bdrv_qed_co_create(BlockdevCreateOptions *opts,
* The QED format associates file length with allocation status,
* so a new file (which is empty) must have a length of 0.
*/
ret = blk_truncate(blk, 0, true, PREALLOC_MODE_OFF, errp);
ret = blk_truncate(blk, 0, true, PREALLOC_MODE_OFF, 0, errp);
if (ret < 0) {
goto out;
}
@@ -1467,6 +1467,7 @@ static int coroutine_fn bdrv_qed_co_truncate(BlockDriverState *bs,
int64_t offset,
bool exact,
PreallocMode prealloc,
BdrvRequestFlags flags,
Error **errp)
{
BDRVQEDState *s = bs->opaque;
+4 -2
View File
@@ -371,7 +371,7 @@ static void raw_refresh_limits(BlockDriverState *bs, Error **errp)
static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset,
bool exact, PreallocMode prealloc,
Error **errp)
BdrvRequestFlags flags, Error **errp)
{
BDRVRawState *s = bs->opaque;
@@ -387,7 +387,7 @@ static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset,
s->size = offset;
offset += s->offset;
return bdrv_co_truncate(bs->file, offset, exact, prealloc, errp);
return bdrv_co_truncate(bs->file, offset, exact, prealloc, flags, errp);
}
static void raw_eject(BlockDriverState *bs, bool eject_flag)
@@ -445,6 +445,8 @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags,
bs->supported_zero_flags = BDRV_REQ_WRITE_UNCHANGED |
((BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK) &
bs->file->bs->supported_zero_flags);
bs->supported_truncate_flags = bs->file->bs->supported_truncate_flags &
BDRV_REQ_ZERO_WRITE;
if (bs->probed && !bdrv_is_read_only(bs)) {
bdrv_refresh_filename(bs->file->bs);
+1
View File
@@ -1108,6 +1108,7 @@ static int coroutine_fn qemu_rbd_co_truncate(BlockDriverState *bs,
int64_t offset,
bool exact,
PreallocMode prealloc,
BdrvRequestFlags flags,
Error **errp)
{
int r;
+2 -2
View File
@@ -2281,7 +2281,7 @@ static int64_t sd_getlength(BlockDriverState *bs)
static int coroutine_fn sd_co_truncate(BlockDriverState *bs, int64_t offset,
bool exact, PreallocMode prealloc,
Error **errp)
BdrvRequestFlags flags, Error **errp)
{
BDRVSheepdogState *s = bs->opaque;
int ret, fd;
@@ -2597,7 +2597,7 @@ static coroutine_fn int sd_co_writev(BlockDriverState *bs, int64_t sector_num,
assert(!flags);
if (offset > s->inode.vdi_size) {
ret = sd_co_truncate(bs, offset, false, PREALLOC_MODE_OFF, NULL);
ret = sd_co_truncate(bs, offset, false, PREALLOC_MODE_OFF, 0, NULL);
if (ret < 0) {
return ret;
}

Some files were not shown because too many files have changed in this diff Show More