block/qcow2: Metadata preallocation for truncate
We can support PREALLOC_MODE_METADATA by invoking preallocate() in qcow2_truncate(). Signed-off-by: Max Reitz <mreitz@redhat.com> Message-id: 20170613202107.10125-12-mreitz@redhat.com Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> Signed-off-by: Max Reitz <mreitz@redhat.com>
This commit is contained in:
parent
652fecd005
commit
95b98f343b
@ -3077,10 +3077,11 @@ static int qcow2_truncate(BlockDriverState *bs, int64_t offset,
|
|||||||
PreallocMode prealloc, Error **errp)
|
PreallocMode prealloc, Error **errp)
|
||||||
{
|
{
|
||||||
BDRVQcow2State *s = bs->opaque;
|
BDRVQcow2State *s = bs->opaque;
|
||||||
|
uint64_t old_length;
|
||||||
int64_t new_l1_size;
|
int64_t new_l1_size;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (prealloc != PREALLOC_MODE_OFF) {
|
if (prealloc != PREALLOC_MODE_OFF && prealloc != PREALLOC_MODE_METADATA) {
|
||||||
error_setg(errp, "Unsupported preallocation mode '%s'",
|
error_setg(errp, "Unsupported preallocation mode '%s'",
|
||||||
PreallocMode_lookup[prealloc]);
|
PreallocMode_lookup[prealloc]);
|
||||||
return -ENOTSUP;
|
return -ENOTSUP;
|
||||||
@ -3104,8 +3105,10 @@ static int qcow2_truncate(BlockDriverState *bs, int64_t offset,
|
|||||||
return -ENOTSUP;
|
return -ENOTSUP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
old_length = bs->total_sectors * 512;
|
||||||
|
|
||||||
/* shrinking is currently not supported */
|
/* shrinking is currently not supported */
|
||||||
if (offset < bs->total_sectors * 512) {
|
if (offset < old_length) {
|
||||||
error_setg(errp, "qcow2 doesn't support shrinking images yet");
|
error_setg(errp, "qcow2 doesn't support shrinking images yet");
|
||||||
return -ENOTSUP;
|
return -ENOTSUP;
|
||||||
}
|
}
|
||||||
@ -3117,6 +3120,32 @@ static int qcow2_truncate(BlockDriverState *bs, int64_t offset,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch (prealloc) {
|
||||||
|
case PREALLOC_MODE_OFF:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PREALLOC_MODE_METADATA:
|
||||||
|
ret = preallocate(bs, old_length, offset);
|
||||||
|
if (ret < 0) {
|
||||||
|
error_setg_errno(errp, -ret, "Preallocation failed");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
g_assert_not_reached();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prealloc != PREALLOC_MODE_OFF) {
|
||||||
|
/* Flush metadata before actually changing the image size */
|
||||||
|
ret = bdrv_flush(bs);
|
||||||
|
if (ret < 0) {
|
||||||
|
error_setg_errno(errp, -ret,
|
||||||
|
"Failed to flush the preallocated area to disk");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* write updated header.size */
|
/* write updated header.size */
|
||||||
offset = cpu_to_be64(offset);
|
offset = cpu_to_be64(offset);
|
||||||
ret = bdrv_pwrite_sync(bs->file, offsetof(QCowHeader, size),
|
ret = bdrv_pwrite_sync(bs->file, offsetof(QCowHeader, size),
|
||||||
|
Loading…
Reference in New Issue
Block a user