diff options
-rw-r--r-- | block.c | 57 | ||||
-rwxr-xr-x | tests/qemu-iotests/060 | 13 | ||||
-rw-r--r-- | tests/qemu-iotests/060.out | 12 |
3 files changed, 53 insertions, 29 deletions
@@ -3198,6 +3198,7 @@ void bdrv_reopen_abort(BDRVReopenState *reopen_state) static void bdrv_close(BlockDriverState *bs) { BdrvAioNotifier *ban, *ban_next; + BdrvChild *child, *next; assert(!bs->job); assert(!bs->refcnt); @@ -3207,43 +3208,41 @@ static void bdrv_close(BlockDriverState *bs) bdrv_drain(bs); /* in case flush left pending I/O */ if (bs->drv) { - BdrvChild *child, *next; - bs->drv->bdrv_close(bs); bs->drv = NULL; + } - bdrv_set_backing_hd(bs, NULL, &error_abort); + bdrv_set_backing_hd(bs, NULL, &error_abort); - if (bs->file != NULL) { - bdrv_unref_child(bs, bs->file); - bs->file = NULL; - } + if (bs->file != NULL) { + bdrv_unref_child(bs, bs->file); + bs->file = NULL; + } - QLIST_FOREACH_SAFE(child, &bs->children, next, next) { - /* TODO Remove bdrv_unref() from drivers' close function and use - * bdrv_unref_child() here */ - if (child->bs->inherits_from == bs) { - child->bs->inherits_from = NULL; - } - bdrv_detach_child(child); + QLIST_FOREACH_SAFE(child, &bs->children, next, next) { + /* TODO Remove bdrv_unref() from drivers' close function and use + * bdrv_unref_child() here */ + if (child->bs->inherits_from == bs) { + child->bs->inherits_from = NULL; } - - g_free(bs->opaque); - bs->opaque = NULL; - atomic_set(&bs->copy_on_read, 0); - bs->backing_file[0] = '\0'; - bs->backing_format[0] = '\0'; - bs->total_sectors = 0; - bs->encrypted = false; - bs->sg = false; - QDECREF(bs->options); - QDECREF(bs->explicit_options); - bs->options = NULL; - bs->explicit_options = NULL; - QDECREF(bs->full_open_options); - bs->full_open_options = NULL; + bdrv_detach_child(child); } + g_free(bs->opaque); + bs->opaque = NULL; + atomic_set(&bs->copy_on_read, 0); + bs->backing_file[0] = '\0'; + bs->backing_format[0] = '\0'; + bs->total_sectors = 0; + bs->encrypted = false; + bs->sg = false; + QDECREF(bs->options); + QDECREF(bs->explicit_options); + bs->options = NULL; + bs->explicit_options = NULL; + QDECREF(bs->full_open_options); + bs->full_open_options = NULL; + bdrv_release_named_dirty_bitmaps(bs); assert(QLIST_EMPTY(&bs->dirty_bitmaps)); diff --git a/tests/qemu-iotests/060 b/tests/qemu-iotests/060 index 1eca09417b..14797dd3b0 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 56f5eb15d8..c4cb7c665e 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 |