From 50a3efb0f05bcfbe04201d4ebac0b96551a1b551 Mon Sep 17 00:00:00 2001 From: Alberto Garcia Date: Mon, 6 Nov 2017 16:53:45 +0200 Subject: block: Close a BlockDriverState completely even when bs->drv is NULL bdrv_close() skips much of its logic when bs->drv is NULL. This is fine when we're closing a BlockDriverState that has just been created (because e.g the initialization process failed), but it's not enough in other cases. For example, when a valid qcow2 image is found to be corrupted then QEMU marks it as such in the file header and then sets bs->drv to NULL in order to make the BlockDriverState unusable. When that BDS is later closed then many of its data structures are not freed (leaking their memory) and none of its children are detached. This results in bdrv_close_all() failing to close all BDSs and making this assertion fail when QEMU is being shut down: bdrv_close_all: Assertion `QTAILQ_EMPTY(&all_bdrv_states)' failed. This patch makes bdrv_close() do the full uninitialization process in all cases. This fixes the problem with corrupted images and still works fine with freshly created BDSs. Signed-off-by: Alberto Garcia Message-id: 20171106145345.12038-1-berto@igalia.com Reviewed-by: Eric Blake Signed-off-by: Max Reitz --- tests/qemu-iotests/060 | 13 +++++++++++++ tests/qemu-iotests/060.out | 12 ++++++++++++ 2 files changed, 25 insertions(+) (limited to 'tests') diff --git a/tests/qemu-iotests/060 b/tests/qemu-iotests/060 index 1eca094..14797dd 100755 --- a/tests/qemu-iotests/060 +++ b/tests/qemu-iotests/060 @@ -426,6 +426,19 @@ echo '--- Repairing ---' _check_test_img -q -r all _check_test_img -r all +echo +echo "=== Testing the QEMU shutdown with a corrupted image ===" +echo +_make_test_img 64M +poke_file "$TEST_IMG" "$rt_offset" "\x00\x00\x00\x00\x00\x00\x00\x00" +echo "{'execute': 'qmp_capabilities'} + {'execute': 'human-monitor-command', + 'arguments': {'command-line': 'qemu-io drive \"write 0 512\"'}} + {'execute': 'quit'}" \ + | $QEMU -qmp stdio -nographic -nodefaults \ + -drive if=none,node-name=drive,file="$TEST_IMG",driver=qcow2 \ + | _filter_qmp | _filter_qemu_io + # success, all done echo "*** done" rm -f $seq.full diff --git a/tests/qemu-iotests/060.out b/tests/qemu-iotests/060.out index 56f5eb1..c4cb7c6 100644 --- a/tests/qemu-iotests/060.out +++ b/tests/qemu-iotests/060.out @@ -399,4 +399,16 @@ The following inconsistencies were found and repaired: Double checking the fixed image now... No errors were found on the image. + +=== Testing the QEMU shutdown with a corrupted image === + +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +qcow2: Marking image as corrupt: Preventing invalid write on metadata (overlaps with refcount table); further corruption events will be suppressed +QMP_VERSION +{"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_IMAGE_CORRUPTED", "data": {"device": "none0", "msg": "Preventing invalid write on metadata (overlaps with refcount table)", "offset": 65536, "node-name": "drive", "fatal": true, "size": 65536}} +write failed: Input/output error +{"return": ""} +{"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}} *** done -- cgit v1.1