aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--block.c16
-rwxr-xr-xtests/qemu-iotests/16135
-rw-r--r--tests/qemu-iotests/161.out16
3 files changed, 66 insertions, 1 deletions
diff --git a/block.c b/block.c
index fe0cdc7d99..5ba3435f8f 100644
--- a/block.c
+++ b/block.c
@@ -3855,6 +3855,8 @@ BlockDriverState *bdrv_find_base(BlockDriverState *bs)
int bdrv_drop_intermediate(BlockDriverState *top, BlockDriverState *base,
const char *backing_file_str)
{
+ BlockDriverState *explicit_top = top;
+ bool update_inherits_from;
BdrvChild *c, *next;
Error *local_err = NULL;
int ret = -EIO;
@@ -3870,6 +3872,16 @@ int bdrv_drop_intermediate(BlockDriverState *top, BlockDriverState *base,
goto exit;
}
+ /* If 'base' recursively inherits from 'top' then we should set
+ * base->inherits_from to top->inherits_from after 'top' and all
+ * other intermediate nodes have been dropped.
+ * If 'top' is an implicit node (e.g. "commit_top") we should skip
+ * it because no one inherits from it. We use explicit_top for that. */
+ while (explicit_top && explicit_top->implicit) {
+ explicit_top = backing_bs(explicit_top);
+ }
+ update_inherits_from = bdrv_inherits_from_recursive(base, explicit_top);
+
/* success - we can delete the intermediate states, and link top->base */
/* TODO Check graph modification op blockers (BLK_PERM_GRAPH_MOD) once
* we've figured out how they should work. */
@@ -3905,6 +3917,10 @@ int bdrv_drop_intermediate(BlockDriverState *top, BlockDriverState *base,
bdrv_unref(top);
}
+ if (update_inherits_from) {
+ base->inherits_from = explicit_top->inherits_from;
+ }
+
ret = 0;
exit:
bdrv_unref(top);
diff --git a/tests/qemu-iotests/161 b/tests/qemu-iotests/161
index 8d0c6afb47..180df17ad6 100755
--- a/tests/qemu-iotests/161
+++ b/tests/qemu-iotests/161
@@ -1,6 +1,6 @@
#!/bin/bash
#
-# Test reopening a backing image after block-stream
+# Test reopening a backing image after block-stream and block-commit
#
# Copyright (C) 2018 Igalia, S.L.
#
@@ -98,6 +98,39 @@ _send_qemu_cmd $QEMU_HANDLE \
_cleanup_qemu
+# Third test: commit $TEST_IMG.int into $TEST_IMG.base and then reopen
+# $TEST.IMG changing the detect-zeroes option on its new backing file
+# ($TEST_IMG.base).
+echo
+echo "*** Commit and then change an option on the backing file"
+echo
+# Create the images again
+TEST_IMG="$TEST_IMG.base" _make_test_img $IMG_SIZE | _filter_imgfmt
+TEST_IMG="$TEST_IMG.int" _make_test_img -b "$TEST_IMG.base" | _filter_imgfmt
+_make_test_img -b "$TEST_IMG.int" | _filter_imgfmt
+
+_launch_qemu -drive if=none,file="${TEST_IMG}"
+_send_qemu_cmd $QEMU_HANDLE \
+ "{ 'execute': 'qmp_capabilities' }" \
+ 'return'
+
+_send_qemu_cmd $QEMU_HANDLE \
+ "{ 'execute': 'block-commit', \
+ 'arguments': { 'device': 'none0',
+ 'top': '${TEST_IMG}.int' } }" \
+ 'return'
+
+# Wait for block-commit to finish
+sleep 0.5
+
+_send_qemu_cmd $QEMU_HANDLE \
+ "{ 'execute': 'human-monitor-command',
+ 'arguments': { 'command-line':
+ 'qemu-io none0 \"reopen -o backing.detect-zeroes=on\"' } }" \
+ "return"
+
+_cleanup_qemu
+
# success, all done
echo "*** done"
rm -f $seq.full
diff --git a/tests/qemu-iotests/161.out b/tests/qemu-iotests/161.out
index a3474717a2..39951993ee 100644
--- a/tests/qemu-iotests/161.out
+++ b/tests/qemu-iotests/161.out
@@ -20,4 +20,20 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "none0"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "none0"}}
{"return": ""}
+
+*** Commit and then change an option on the backing file
+
+Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=1048576
+Formatting 'TEST_DIR/t.IMGFMT.int', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.IMGFMT.base
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.IMGFMT.int
+{"return": {}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "none0"}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "none0"}}
+{"return": {}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "none0"}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "none0"}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "none0", "len": 1048576, "offset": 1048576, "speed": 0, "type": "commit"}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "none0"}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "none0"}}
+{"return": ""}
*** done