Skip to content

Commit a2b333c

Browse files
nirsebblake
authored andcommitted
block: nbd: Fix convert qcow2 compressed to nbd
When converting to qcow2 compressed format, the last step is a special zero length compressed write, ending in a call to bdrv_co_truncate(). This call always fails for the nbd driver since it does not implement bdrv_co_truncate(). For block devices, which have the same limits, the call succeeds since the file driver implements bdrv_co_truncate(). If the caller asked to truncate to the same or smaller size with exact=false, the truncate succeeds. Implement the same logic for nbd. Example failing without this change: In one shell start qemu-nbd: $ truncate -s 1g test.tar $ qemu-nbd --socket=/tmp/nbd.sock --persistent --format=raw --offset 1536 test.tar In another shell convert an image to qcow2 compressed via NBD: $ echo "disk data" > disk.raw $ truncate -s 1g disk.raw $ qemu-img convert -f raw -O qcow2 -c disk1.raw nbd+unix:///?socket=/tmp/nbd.sock; echo $? 1 qemu-img failed, but the conversion was successful: $ qemu-img info nbd+unix:///?socket=/tmp/nbd.sock image: nbd+unix://?socket=/tmp/nbd.sock file format: qcow2 virtual size: 1 GiB (1073741824 bytes) ... $ qemu-img check nbd+unix:///?socket=/tmp/nbd.sock No errors were found on the image. 1/16384 = 0.01% allocated, 100.00% fragmented, 100.00% compressed clusters Image end offset: 393216 $ qemu-img compare disk.raw nbd+unix:///?socket=/tmp/nbd.sock Images are identical. Fixes: https://bugzilla.redhat.com/1860627 Signed-off-by: Nir Soffer <[email protected]> Message-Id: <[email protected]> Reviewed-by: Eric Blake <[email protected]> Reviewed-by: Vladimir Sementsov-Ogievskiy <[email protected]> [eblake: typo fixes] Signed-off-by: Eric Blake <[email protected]>
1 parent 890cbcc commit a2b333c

File tree

2 files changed

+31
-1
lines changed

2 files changed

+31
-1
lines changed

block/nbd.c

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1966,6 +1966,33 @@ static void nbd_close(BlockDriverState *bs)
19661966
nbd_clear_bdrvstate(s);
19671967
}
19681968

1969+
/*
1970+
* NBD cannot truncate, but if the caller asks to truncate to the same size, or
1971+
* to a smaller size with exact=false, there is no reason to fail the
1972+
* operation.
1973+
*
1974+
* Preallocation mode is ignored since it does not seems useful to fail when
1975+
* we never change anything.
1976+
*/
1977+
static int coroutine_fn nbd_co_truncate(BlockDriverState *bs, int64_t offset,
1978+
bool exact, PreallocMode prealloc,
1979+
BdrvRequestFlags flags, Error **errp)
1980+
{
1981+
BDRVNBDState *s = bs->opaque;
1982+
1983+
if (offset != s->info.size && exact) {
1984+
error_setg(errp, "Cannot resize NBD nodes");
1985+
return -ENOTSUP;
1986+
}
1987+
1988+
if (offset > s->info.size) {
1989+
error_setg(errp, "Cannot grow NBD nodes");
1990+
return -EINVAL;
1991+
}
1992+
1993+
return 0;
1994+
}
1995+
19691996
static int64_t nbd_getlength(BlockDriverState *bs)
19701997
{
19711998
BDRVNBDState *s = bs->opaque;
@@ -2045,6 +2072,7 @@ static BlockDriver bdrv_nbd = {
20452072
.bdrv_co_flush_to_os = nbd_co_flush,
20462073
.bdrv_co_pdiscard = nbd_client_co_pdiscard,
20472074
.bdrv_refresh_limits = nbd_refresh_limits,
2075+
.bdrv_co_truncate = nbd_co_truncate,
20482076
.bdrv_getlength = nbd_getlength,
20492077
.bdrv_detach_aio_context = nbd_client_detach_aio_context,
20502078
.bdrv_attach_aio_context = nbd_client_attach_aio_context,
@@ -2072,6 +2100,7 @@ static BlockDriver bdrv_nbd_tcp = {
20722100
.bdrv_co_flush_to_os = nbd_co_flush,
20732101
.bdrv_co_pdiscard = nbd_client_co_pdiscard,
20742102
.bdrv_refresh_limits = nbd_refresh_limits,
2103+
.bdrv_co_truncate = nbd_co_truncate,
20752104
.bdrv_getlength = nbd_getlength,
20762105
.bdrv_detach_aio_context = nbd_client_detach_aio_context,
20772106
.bdrv_attach_aio_context = nbd_client_attach_aio_context,
@@ -2099,6 +2128,7 @@ static BlockDriver bdrv_nbd_unix = {
20992128
.bdrv_co_flush_to_os = nbd_co_flush,
21002129
.bdrv_co_pdiscard = nbd_client_co_pdiscard,
21012130
.bdrv_refresh_limits = nbd_refresh_limits,
2131+
.bdrv_co_truncate = nbd_co_truncate,
21022132
.bdrv_getlength = nbd_getlength,
21032133
.bdrv_detach_aio_context = nbd_client_detach_aio_context,
21042134
.bdrv_attach_aio_context = nbd_client_attach_aio_context,

qemu-io-cmds.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1715,7 +1715,7 @@ static int truncate_f(BlockBackend *blk, int argc, char **argv)
17151715
* exact=true. It is better to err on the "emit more errors" side
17161716
* than to be overly permissive.
17171717
*/
1718-
ret = blk_truncate(blk, offset, true, PREALLOC_MODE_OFF, 0, &local_err);
1718+
ret = blk_truncate(blk, offset, false, PREALLOC_MODE_OFF, 0, &local_err);
17191719
if (ret < 0) {
17201720
error_report_err(local_err);
17211721
return ret;

0 commit comments

Comments
 (0)