aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoryuchenlin <yuchenlin@synology.com>2018-09-13 16:29:52 +0800
committerFam Zheng <famz@redhat.com>2018-09-26 10:47:18 +0800
commit51b3c6b73acae1e3fd3c7d441fc86dd17356695f (patch)
treeb361ef7669c1a9ebcdf2dd9695a280c15d7e8949
parentb33bd859d12e70757bb2632573c3a1662d967dbf (diff)
vmdk: align end of file to a sector boundary
There is a rare case which the size of last compressed cluster is larger than the cluster size, which will cause the file is not aligned at the sector boundary. There are three reasons to do it. First, if vmdk doesn't align at the sector boundary, there may be many undefined behaviors, such as, in vbox it will show VMDK: Compressed image is corrupted 'syno-vm-disk1.vmdk' (VERR_ZIP_CORRUPTED) when we try to import an ova with unaligned vmdk. Second, all the cluster_sector is aligned to sector, the last one should be like this, too. Third, it ease reading with sector based I/Os. Signed-off-by: yuchenlin <yuchenlin@synology.com> Message-Id: <20180913082952.3675-1-yuchenlin@synology.com> Reviewed-by: Fam Zheng <famz@redhat.com> Signed-off-by: Fam Zheng <famz@redhat.com>
-rw-r--r--block/vmdk.c21
1 files changed, 21 insertions, 0 deletions
diff --git a/block/vmdk.c b/block/vmdk.c
index a9d0084e36..2c9e86d98f 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -1698,6 +1698,27 @@ static int coroutine_fn
vmdk_co_pwritev_compressed(BlockDriverState *bs, uint64_t offset,
uint64_t bytes, QEMUIOVector *qiov)
{
+ if (bytes == 0) {
+ /* The caller will write bytes 0 to signal EOF.
+ * When receive it, we align EOF to a sector boundary. */
+ BDRVVmdkState *s = bs->opaque;
+ int i, ret;
+ int64_t length;
+
+ for (i = 0; i < s->num_extents; i++) {
+ length = bdrv_getlength(s->extents[i].file->bs);
+ if (length < 0) {
+ return length;
+ }
+ length = QEMU_ALIGN_UP(length, BDRV_SECTOR_SIZE);
+ ret = bdrv_truncate(s->extents[i].file, length,
+ PREALLOC_MODE_OFF, NULL);
+ if (ret < 0) {
+ return ret;
+ }
+ }
+ return 0;
+ }
return vmdk_co_pwritev(bs, offset, bytes, qiov, 0);
}