Commit 048c5fd1 authored by Eric Blake's avatar Eric Blake Committed by Max Reitz
Browse files

qcow2: Allow discard of final unaligned cluster



As mentioned in commit 0c1bd469, we ignored requests to
discard the trailing cluster of an unaligned image.  While
discard is an advisory operation from the guest standpoint,
(and we are therefore free to ignore any request), our
qcow2 implementation exploits the fact that a discarded
cluster reads back as 0.  As long as we discard on cluster
boundaries, we are fine; but that means we could observe
non-zero data leaked at the tail of an unaligned image.

Enhance iotest 66 to cover this case, and fix the implementation
to honor a discard request on the final partial cluster.

Signed-off-by: default avatarEric Blake <eblake@redhat.com>
Message-id: 20170407013709.18440-1-eblake@redhat.com
Signed-off-by: default avatarMax Reitz <mreitz@redhat.com>
parent f59adb32
Loading
Loading
Loading
Loading
+6 −1
Original line number Diff line number Diff line
@@ -2515,8 +2515,13 @@ static coroutine_fn int qcow2_co_pdiscard(BlockDriverState *bs,

    if (!QEMU_IS_ALIGNED(offset | count, s->cluster_size)) {
        assert(count < s->cluster_size);
        /* 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);
    ret = qcow2_discard_clusters(bs, offset, count >> BDRV_SECTOR_BITS,
+7 −5
Original line number Diff line number Diff line
@@ -42,16 +42,18 @@ _supported_fmt qcow2
_supported_proto generic
_supported_os Linux

# Intentionally create an unaligned image
IMGOPTS="compat=1.1"
IMG_SIZE=64M
IMG_SIZE=$((64 * 1024 * 1024 + 512))

echo
echo "=== Testing snapshotting an image with zero clusters ==="
echo "=== Testing cluster discards ==="
echo
_make_test_img $IMG_SIZE
# Write some normal clusters, zero them (creating preallocated zero clusters)
# and discard those
$QEMU_IO -c "write 0 256k" -c "write -z 0 256k" -c "discard 0 256k" "$TEST_IMG" \
# Write some normal clusters, zero some of them (creating preallocated
# zero clusters) and discard everything. Everything should now read as 0.
$QEMU_IO -c "write 0 256k" -c "write -z 0 256k" -c "write 64M 512" \
	 -c "discard 0 $IMG_SIZE" -c "read -P 0 0 $IMG_SIZE" "$TEST_IMG" \
         | _filter_qemu_io
# Check the image (there shouldn't be any leaks)
_check_test_img
+8 −4
Original line number Diff line number Diff line
QA output created by 066

=== Testing snapshotting an image with zero clusters ===
=== Testing cluster discards ===

Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67109376
wrote 262144/262144 bytes at offset 0
256 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
wrote 262144/262144 bytes at offset 0
256 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
discard 262144/262144 bytes at offset 0
256 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
wrote 512/512 bytes at offset 67108864
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
discard 67109376/67109376 bytes at offset 0
64 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
read 67109376/67109376 bytes at offset 0
64 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
No errors were found on the image.
*** done