1 | The following changes since commit 521db80318d6c749a6f6c5a65a68397af9e3ef16: | 1 | The following changes since commit 7bc8f9734213b76e76631a483be13d6737c2adbc: |
---|---|---|---|
2 | 2 | ||
3 | Merge remote-tracking branch 'remotes/maxreitz/tags/pull-block-2019-09-16' into staging (2019-09-16 15:25:55 +0100) | 3 | Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20191025' into staging (2019-10-25 13:12:16 +0100) |
4 | 4 | ||
5 | are available in the Git repository at: | 5 | are available in the Git repository at: |
6 | 6 | ||
7 | git://repo.or.cz/qemu/kevin.git tags/for-upstream | 7 | git://repo.or.cz/qemu/kevin.git tags/for-upstream |
8 | 8 | ||
9 | for you to fetch changes up to d2c8c09fca9210d0f2399c8d570086a4a66bd22e: | 9 | for you to fetch changes up to 5e9785505210e2477e590e61b1ab100d0ec22b01: |
10 | 10 | ||
11 | iotests: Remove Python 2 compatibility code (2019-09-20 17:58:51 +0200) | 11 | qcow2: Fix corruption bug in qcow2_detect_metadata_preallocation() (2019-10-25 15:18:55 +0200) |
12 | 12 | ||
13 | ---------------------------------------------------------------- | 13 | ---------------------------------------------------------------- |
14 | Block layer patches: | 14 | Block layer patches: |
15 | 15 | ||
16 | - Fix internal snapshots with typical -blockdev setups | 16 | - qcow2: Fix data corruption bug that is triggered in partial cluster |
17 | - iotests: Require Python 3.6 or later | 17 | allocation with default options |
18 | - qapi: add support for blkreplay driver | ||
19 | - doc: Describe missing generic -blockdev options | ||
20 | - iotests: Fix 118 when run as root | ||
21 | - Minor code cleanups | ||
18 | 22 | ||
19 | ---------------------------------------------------------------- | 23 | ---------------------------------------------------------------- |
20 | Kevin Wolf (4): | 24 | Kevin Wolf (5): |
21 | block/snapshot: Restrict set of snapshot nodes | 25 | iotests: Skip read-only cases in 118 when run as root |
22 | iotests: Test internal snapshots with -blockdev | 26 | blockdev: Use error_report() in hmp_commit() |
23 | iotests: Require Python 3.6 or later | 27 | doc: Describe missing generic -blockdev options |
24 | iotests: Remove Python 2 compatibility code | 28 | coroutine: Add qemu_co_mutex_assert_locked() |
29 | qcow2: Fix corruption bug in qcow2_detect_metadata_preallocation() | ||
25 | 30 | ||
26 | block/snapshot.c | 26 +++-- | 31 | Pavel Dovgaluk (1): |
27 | tests/qemu-iotests/044 | 3 - | 32 | qapi: add support for blkreplay driver |
28 | tests/qemu-iotests/163 | 3 - | ||
29 | tests/qemu-iotests/267 | 168 ++++++++++++++++++++++++++++ | ||
30 | tests/qemu-iotests/267.out | 182 +++++++++++++++++++++++++++++++ | ||
31 | tests/qemu-iotests/check | 13 ++- | ||
32 | tests/qemu-iotests/common.filter | 5 +- | ||
33 | tests/qemu-iotests/group | 1 + | ||
34 | tests/qemu-iotests/iotests.py | 13 +-- | ||
35 | tests/qemu-iotests/nbd-fault-injector.py | 7 +- | ||
36 | 10 files changed, 389 insertions(+), 32 deletions(-) | ||
37 | create mode 100755 tests/qemu-iotests/267 | ||
38 | create mode 100644 tests/qemu-iotests/267.out | ||
39 | 33 | ||
34 | Vladimir Sementsov-Ogievskiy (1): | ||
35 | block/backup: drop dead code from backup_job_create | ||
36 | |||
37 | qapi/block-core.json | 18 ++++++++++++++++-- | ||
38 | include/qemu/coroutine.h | 15 +++++++++++++++ | ||
39 | block/backup.c | 5 +---- | ||
40 | block/qcow2-refcount.c | 2 ++ | ||
41 | block/qcow2.c | 3 ++- | ||
42 | blockdev.c | 7 +++---- | ||
43 | qemu-options.hx | 22 +++++++++++++++++++++- | ||
44 | tests/qemu-iotests/118 | 3 +++ | ||
45 | tests/qemu-iotests/iotests.py | 10 ++++++++++ | ||
46 | 9 files changed, 73 insertions(+), 12 deletions(-) | ||
47 | |||
48 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Pavel Dovgalyuk <pavel.dovgaluk@gmail.com> | ||
1 | 2 | ||
3 | This patch adds support for blkreplay driver to the blockdev options. | ||
4 | Now blkreplay can be used with -blockdev command line option | ||
5 | in the following format: | ||
6 | -blockdev driver=blkreplay,image=file-node-name,node-name=replay-node-name | ||
7 | |||
8 | This option makes possible implementation of the better command | ||
9 | line support for record/replay invocations. | ||
10 | |||
11 | Signed-off-by: Pavel Dovgalyuk <Pavel.Dovgaluk@ispras.ru> | ||
12 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
13 | --- | ||
14 | qapi/block-core.json | 18 ++++++++++++++++-- | ||
15 | 1 file changed, 16 insertions(+), 2 deletions(-) | ||
16 | |||
17 | diff --git a/qapi/block-core.json b/qapi/block-core.json | ||
18 | index XXXXXXX..XXXXXXX 100644 | ||
19 | --- a/qapi/block-core.json | ||
20 | +++ b/qapi/block-core.json | ||
21 | @@ -XXX,XX +XXX,XX @@ | ||
22 | # @nvme: Since 2.12 | ||
23 | # @copy-on-read: Since 3.0 | ||
24 | # @blklogwrites: Since 3.0 | ||
25 | +# @blkreplay: Since 4.2 | ||
26 | # | ||
27 | # Since: 2.9 | ||
28 | ## | ||
29 | { 'enum': 'BlockdevDriver', | ||
30 | - 'data': [ 'blkdebug', 'blklogwrites', 'blkverify', 'bochs', 'cloop', | ||
31 | - 'copy-on-read', 'dmg', 'file', 'ftp', 'ftps', 'gluster', | ||
32 | + 'data': [ 'blkdebug', 'blklogwrites', 'blkreplay', 'blkverify', 'bochs', | ||
33 | + 'cloop', 'copy-on-read', 'dmg', 'file', 'ftp', 'ftps', 'gluster', | ||
34 | 'host_cdrom', 'host_device', 'http', 'https', 'iscsi', 'luks', | ||
35 | 'nbd', 'nfs', 'null-aio', 'null-co', 'nvme', 'parallels', 'qcow', | ||
36 | 'qcow2', 'qed', 'quorum', 'raw', 'rbd', | ||
37 | @@ -XXX,XX +XXX,XX @@ | ||
38 | 'data': { 'test': 'BlockdevRef', | ||
39 | 'raw': 'BlockdevRef' } } | ||
40 | |||
41 | +## | ||
42 | +# @BlockdevOptionsBlkreplay: | ||
43 | +# | ||
44 | +# Driver specific block device options for blkreplay. | ||
45 | +# | ||
46 | +# @image: disk image which should be controlled with blkreplay | ||
47 | +# | ||
48 | +# Since: 4.2 | ||
49 | +## | ||
50 | +{ 'struct': 'BlockdevOptionsBlkreplay', | ||
51 | + 'data': { 'image': 'BlockdevRef' } } | ||
52 | + | ||
53 | ## | ||
54 | # @QuorumReadPattern: | ||
55 | # | ||
56 | @@ -XXX,XX +XXX,XX @@ | ||
57 | 'blkdebug': 'BlockdevOptionsBlkdebug', | ||
58 | 'blklogwrites':'BlockdevOptionsBlklogwrites', | ||
59 | 'blkverify': 'BlockdevOptionsBlkverify', | ||
60 | + 'blkreplay': 'BlockdevOptionsBlkreplay', | ||
61 | 'bochs': 'BlockdevOptionsGenericFormat', | ||
62 | 'cloop': 'BlockdevOptionsGenericFormat', | ||
63 | 'copy-on-read':'BlockdevOptionsGenericFormat', | ||
64 | -- | ||
65 | 2.20.1 | ||
66 | |||
67 | diff view generated by jsdifflib |
1 | Some scripts check the Python version number and have two code paths to | 1 | Some tests in 118 use chmod to remove write permissions from the file |
---|---|---|---|
2 | accomodate both Python 2 and 3. Remove the code specific to Python 2 and | 2 | and assume that the image can indeed not be opened read-write |
3 | assert the minimum version of 3.6 instead (check skips Python tests in | 3 | afterwards. This doesn't work when the test is run as root, because root |
4 | this case, so the assertion would only ever trigger if a Python script | 4 | can still open the file as writable even when the permission bit isn't |
5 | is executed manually). | 5 | set. |
6 | |||
7 | Introduce a @skip_if_root decorator and use it in 118 to skip the tests | ||
8 | in question when the script is run as root. | ||
6 | 9 | ||
7 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | 10 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> |
8 | Reviewed-by: Eduardo Habkost <ehabkost@redhat.com> | ||
9 | Reviewed-by: Thomas Huth <thuth@redhat.com> | ||
10 | Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com> | 11 | Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com> |
11 | Reviewed-by: John Snow <jsnow@redhat.com> | ||
12 | Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> | ||
13 | --- | 12 | --- |
14 | tests/qemu-iotests/044 | 3 --- | 13 | tests/qemu-iotests/118 | 3 +++ |
15 | tests/qemu-iotests/163 | 3 --- | 14 | tests/qemu-iotests/iotests.py | 10 ++++++++++ |
16 | tests/qemu-iotests/iotests.py | 13 +++---------- | 15 | 2 files changed, 13 insertions(+) |
17 | tests/qemu-iotests/nbd-fault-injector.py | 7 +++---- | ||
18 | 4 files changed, 6 insertions(+), 20 deletions(-) | ||
19 | 16 | ||
20 | diff --git a/tests/qemu-iotests/044 b/tests/qemu-iotests/044 | 17 | diff --git a/tests/qemu-iotests/118 b/tests/qemu-iotests/118 |
21 | index XXXXXXX..XXXXXXX 100755 | 18 | index XXXXXXX..XXXXXXX 100755 |
22 | --- a/tests/qemu-iotests/044 | 19 | --- a/tests/qemu-iotests/118 |
23 | +++ b/tests/qemu-iotests/044 | 20 | +++ b/tests/qemu-iotests/118 |
24 | @@ -XXX,XX +XXX,XX @@ import struct | 21 | @@ -XXX,XX +XXX,XX @@ class TestChangeReadOnly(ChangeBaseClass): |
25 | import subprocess | 22 | self.assert_qmp(result, 'return[0]/inserted/ro', True) |
26 | import sys | 23 | self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) |
27 | 24 | ||
28 | -if sys.version_info.major == 2: | 25 | + @iotests.skip_if_user_is_root |
29 | - range = xrange | 26 | def test_rw_ro_retain(self): |
30 | - | 27 | os.chmod(new_img, 0o444) |
31 | test_img = os.path.join(iotests.test_dir, 'test.img') | 28 | self.vm.add_drive(old_img, 'media=disk', 'none') |
32 | 29 | @@ -XXX,XX +XXX,XX @@ class TestChangeReadOnly(ChangeBaseClass): | |
33 | class TestRefcountTableGrowth(iotests.QMPTestCase): | 30 | self.assert_qmp(result, 'return[0]/inserted/ro', True) |
34 | diff --git a/tests/qemu-iotests/163 b/tests/qemu-iotests/163 | 31 | self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) |
35 | index XXXXXXX..XXXXXXX 100755 | 32 | |
36 | --- a/tests/qemu-iotests/163 | 33 | + @iotests.skip_if_user_is_root |
37 | +++ b/tests/qemu-iotests/163 | 34 | def test_make_ro_rw(self): |
38 | @@ -XXX,XX +XXX,XX @@ | 35 | os.chmod(new_img, 0o444) |
39 | import os, random, iotests, struct, qcow2, sys | 36 | self.vm.add_drive(old_img, 'media=disk', 'none') |
40 | from iotests import qemu_img, qemu_io, image_size | 37 | @@ -XXX,XX +XXX,XX @@ class TestChangeReadOnly(ChangeBaseClass): |
41 | 38 | self.assert_qmp(result, 'return[0]/inserted/ro', True) | |
42 | -if sys.version_info.major == 2: | 39 | self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) |
43 | - range = xrange | 40 | |
44 | - | 41 | + @iotests.skip_if_user_is_root |
45 | test_img = os.path.join(iotests.test_dir, 'test.img') | 42 | def test_make_ro_rw_by_retain(self): |
46 | check_img = os.path.join(iotests.test_dir, 'check.img') | 43 | os.chmod(new_img, 0o444) |
47 | 44 | self.vm.add_drive(old_img, 'media=disk', 'none') | |
48 | diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py | 45 | diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py |
49 | index XXXXXXX..XXXXXXX 100644 | 46 | index XXXXXXX..XXXXXXX 100644 |
50 | --- a/tests/qemu-iotests/iotests.py | 47 | --- a/tests/qemu-iotests/iotests.py |
51 | +++ b/tests/qemu-iotests/iotests.py | 48 | +++ b/tests/qemu-iotests/iotests.py |
52 | @@ -XXX,XX +XXX,XX @@ from collections import OrderedDict | 49 | @@ -XXX,XX +XXX,XX @@ def skip_if_unsupported(required_formats=[], read_only=False): |
53 | sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'python')) | 50 | return func_wrapper |
54 | from qemu import qtest | 51 | return skip_test_decorator |
55 | 52 | ||
56 | +assert sys.version_info >= (3,6) | 53 | +def skip_if_user_is_root(func): |
57 | 54 | + '''Skip Test Decorator | |
58 | # This will not work if arguments contain spaces but is necessary if we | 55 | + Runs the test only without root permissions''' |
59 | # want to support the override options that ./check supports. | 56 | + def func_wrapper(*args, **kwargs): |
60 | @@ -XXX,XX +XXX,XX @@ def image_size(img): | 57 | + if os.getuid() == 0: |
61 | return json.loads(r)['virtual-size'] | 58 | + case_notrun('{}: cannot be run as root'.format(args[0])) |
62 | 59 | + else: | |
63 | def is_str(val): | 60 | + return func(*args, **kwargs) |
64 | - if sys.version_info.major >= 3: | 61 | + return func_wrapper |
65 | - return isinstance(val, str) | ||
66 | - else: | ||
67 | - return isinstance(val, str) or isinstance(val, unicode) | ||
68 | + return isinstance(val, str) | ||
69 | |||
70 | test_dir_re = re.compile(r"%s" % test_dir) | ||
71 | def filter_test_dir(msg): | ||
72 | @@ -XXX,XX +XXX,XX @@ def execute_test(test_function=None, | ||
73 | else: | ||
74 | # We need to filter out the time taken from the output so that | ||
75 | # qemu-iotest can reliably diff the results against master output. | ||
76 | - if sys.version_info.major >= 3: | ||
77 | - output = io.StringIO() | ||
78 | - else: | ||
79 | - # io.StringIO is for unicode strings, which is not what | ||
80 | - # 2.x's test runner emits. | ||
81 | - output = io.BytesIO() | ||
82 | + output = io.StringIO() | ||
83 | |||
84 | logging.basicConfig(level=(logging.DEBUG if debug else logging.WARN)) | ||
85 | |||
86 | diff --git a/tests/qemu-iotests/nbd-fault-injector.py b/tests/qemu-iotests/nbd-fault-injector.py | ||
87 | index XXXXXXX..XXXXXXX 100755 | ||
88 | --- a/tests/qemu-iotests/nbd-fault-injector.py | ||
89 | +++ b/tests/qemu-iotests/nbd-fault-injector.py | ||
90 | @@ -XXX,XX +XXX,XX @@ import sys | ||
91 | import socket | ||
92 | import struct | ||
93 | import collections | ||
94 | -if sys.version_info.major >= 3: | ||
95 | - import configparser | ||
96 | -else: | ||
97 | - import ConfigParser as configparser | ||
98 | +import configparser | ||
99 | + | 62 | + |
100 | +assert sys.version_info >= (3,6) | 63 | def execute_unittest(output, verbosity, debug): |
101 | 64 | runner = unittest.TextTestRunner(stream=output, descriptions=True, | |
102 | FAKE_DISK_SIZE = 8 * 1024 * 1024 * 1024 # 8 GB | 65 | verbosity=verbosity) |
103 | |||
104 | -- | 66 | -- |
105 | 2.20.1 | 67 | 2.20.1 |
106 | 68 | ||
107 | 69 | diff view generated by jsdifflib |
1 | Instead of using monitor_printf() to report errors, hmp_commit() should | ||
---|---|---|---|
2 | use error_report() like other places do. | ||
3 | |||
1 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | 4 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> |
2 | Reviewed-by: Peter Krempa <pkrempa@redhat.com> | 5 | Reviewed-by: Eric Blake <eblake@redhat.com> |
3 | Tested-by: Peter Krempa <pkrempa@redhat.com> | 6 | Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com> |
4 | --- | 7 | --- |
5 | tests/qemu-iotests/267 | 168 ++++++++++++++++++++++++++++ | 8 | blockdev.c | 7 +++---- |
6 | tests/qemu-iotests/267.out | 182 +++++++++++++++++++++++++++++++ | 9 | 1 file changed, 3 insertions(+), 4 deletions(-) |
7 | tests/qemu-iotests/common.filter | 5 +- | ||
8 | tests/qemu-iotests/group | 1 + | ||
9 | 4 files changed, 352 insertions(+), 4 deletions(-) | ||
10 | create mode 100755 tests/qemu-iotests/267 | ||
11 | create mode 100644 tests/qemu-iotests/267.out | ||
12 | 10 | ||
13 | diff --git a/tests/qemu-iotests/267 b/tests/qemu-iotests/267 | 11 | diff --git a/blockdev.c b/blockdev.c |
14 | new file mode 100755 | ||
15 | index XXXXXXX..XXXXXXX | ||
16 | --- /dev/null | ||
17 | +++ b/tests/qemu-iotests/267 | ||
18 | @@ -XXX,XX +XXX,XX @@ | ||
19 | +#!/usr/bin/env bash | ||
20 | +# | ||
21 | +# Test which nodes are involved in internal snapshots | ||
22 | +# | ||
23 | +# Copyright (C) 2019 Red Hat, Inc. | ||
24 | +# | ||
25 | +# This program is free software; you can redistribute it and/or modify | ||
26 | +# it under the terms of the GNU General Public License as published by | ||
27 | +# the Free Software Foundation; either version 2 of the License, or | ||
28 | +# (at your option) any later version. | ||
29 | +# | ||
30 | +# This program is distributed in the hope that it will be useful, | ||
31 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
32 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
33 | +# GNU General Public License for more details. | ||
34 | +# | ||
35 | +# You should have received a copy of the GNU General Public License | ||
36 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
37 | +# | ||
38 | + | ||
39 | +# creator | ||
40 | +owner=kwolf@redhat.com | ||
41 | + | ||
42 | +seq=`basename $0` | ||
43 | +echo "QA output created by $seq" | ||
44 | + | ||
45 | +status=1 # failure is the default! | ||
46 | + | ||
47 | +_cleanup() | ||
48 | +{ | ||
49 | + _cleanup_test_img | ||
50 | + rm -f "$TEST_DIR/nbd" | ||
51 | +} | ||
52 | +trap "_cleanup; exit \$status" 0 1 2 3 15 | ||
53 | + | ||
54 | +# get standard environment, filters and checks | ||
55 | +. ./common.rc | ||
56 | +. ./common.filter | ||
57 | + | ||
58 | +_supported_fmt qcow2 | ||
59 | +_supported_proto file | ||
60 | +_supported_os Linux | ||
61 | + | ||
62 | +# Internal snapshots are (currently) impossible with refcount_bits=1 | ||
63 | +_unsupported_imgopts 'refcount_bits=1[^0-9]' | ||
64 | + | ||
65 | +do_run_qemu() | ||
66 | +{ | ||
67 | + echo Testing: "$@" | ||
68 | + ( | ||
69 | + if ! test -t 0; then | ||
70 | + while read cmd; do | ||
71 | + echo $cmd | ||
72 | + done | ||
73 | + fi | ||
74 | + echo quit | ||
75 | + ) | $QEMU -nographic -monitor stdio -nodefaults "$@" | ||
76 | + echo | ||
77 | +} | ||
78 | + | ||
79 | +run_qemu() | ||
80 | +{ | ||
81 | + do_run_qemu "$@" 2>&1 | _filter_testdir | _filter_qemu | _filter_hmp | | ||
82 | + _filter_generated_node_ids | _filter_imgfmt | ||
83 | +} | ||
84 | + | ||
85 | +size=128M | ||
86 | + | ||
87 | +run_test() | ||
88 | +{ | ||
89 | + _make_test_img $size | ||
90 | + printf "savevm snap0\ninfo snapshots\nloadvm snap0\n" | run_qemu "$@" | _filter_date | ||
91 | +} | ||
92 | + | ||
93 | + | ||
94 | +echo | ||
95 | +echo "=== No block devices at all ===" | ||
96 | +echo | ||
97 | + | ||
98 | +run_test | ||
99 | + | ||
100 | +echo | ||
101 | +echo "=== -drive if=none ===" | ||
102 | +echo | ||
103 | + | ||
104 | +run_test -drive driver=file,file="$TEST_IMG",if=none | ||
105 | +run_test -drive driver=$IMGFMT,file="$TEST_IMG",if=none | ||
106 | +run_test -drive driver=$IMGFMT,file="$TEST_IMG",if=none -device virtio-blk,drive=none0 | ||
107 | + | ||
108 | +echo | ||
109 | +echo "=== -drive if=virtio ===" | ||
110 | +echo | ||
111 | + | ||
112 | +run_test -drive driver=file,file="$TEST_IMG",if=virtio | ||
113 | +run_test -drive driver=$IMGFMT,file="$TEST_IMG",if=virtio | ||
114 | + | ||
115 | +echo | ||
116 | +echo "=== Simple -blockdev ===" | ||
117 | +echo | ||
118 | + | ||
119 | +run_test -blockdev driver=file,filename="$TEST_IMG",node-name=file | ||
120 | +run_test -blockdev driver=file,filename="$TEST_IMG",node-name=file \ | ||
121 | + -blockdev driver=$IMGFMT,file=file,node-name=fmt | ||
122 | +run_test -blockdev driver=file,filename="$TEST_IMG",node-name=file \ | ||
123 | + -blockdev driver=raw,file=file,node-name=raw \ | ||
124 | + -blockdev driver=$IMGFMT,file=raw,node-name=fmt | ||
125 | + | ||
126 | +echo | ||
127 | +echo "=== -blockdev with a filter on top ===" | ||
128 | +echo | ||
129 | + | ||
130 | +run_test -blockdev driver=file,filename="$TEST_IMG",node-name=file \ | ||
131 | + -blockdev driver=$IMGFMT,file=file,node-name=fmt \ | ||
132 | + -blockdev driver=copy-on-read,file=fmt,node-name=filter | ||
133 | + | ||
134 | +echo | ||
135 | +echo "=== -blockdev with a backing file ===" | ||
136 | +echo | ||
137 | + | ||
138 | +TEST_IMG="$TEST_IMG.base" _make_test_img $size | ||
139 | + | ||
140 | +IMGOPTS="backing_file=$TEST_IMG.base" \ | ||
141 | +run_test -blockdev driver=file,filename="$TEST_IMG.base",node-name=backing-file \ | ||
142 | + -blockdev driver=file,filename="$TEST_IMG",node-name=file \ | ||
143 | + -blockdev driver=$IMGFMT,file=file,backing=backing-file,node-name=fmt | ||
144 | + | ||
145 | +IMGOPTS="backing_file=$TEST_IMG.base" \ | ||
146 | +run_test -blockdev driver=file,filename="$TEST_IMG.base",node-name=backing-file \ | ||
147 | + -blockdev driver=$IMGFMT,file=backing-file,node-name=backing-fmt \ | ||
148 | + -blockdev driver=file,filename="$TEST_IMG",node-name=file \ | ||
149 | + -blockdev driver=$IMGFMT,file=file,backing=backing-fmt,node-name=fmt | ||
150 | + | ||
151 | +# A snapshot should be present on the overlay, but not the backing file | ||
152 | +echo Internal snapshots on overlay: | ||
153 | +$QEMU_IMG snapshot -l "$TEST_IMG" | _filter_date | ||
154 | + | ||
155 | +echo Internal snapshots on backing file: | ||
156 | +$QEMU_IMG snapshot -l "$TEST_IMG.base" | _filter_date | ||
157 | + | ||
158 | +echo | ||
159 | +echo "=== -blockdev with NBD server on the backing file ===" | ||
160 | +echo | ||
161 | + | ||
162 | +IMGOPTS="backing_file=$TEST_IMG.base" _make_test_img $size | ||
163 | +cat <<EOF | | ||
164 | +nbd_server_start unix:$TEST_DIR/nbd | ||
165 | +nbd_server_add -w backing-fmt | ||
166 | +savevm snap0 | ||
167 | +info snapshots | ||
168 | +loadvm snap0 | ||
169 | +EOF | ||
170 | +run_qemu -blockdev driver=file,filename="$TEST_IMG.base",node-name=backing-file \ | ||
171 | + -blockdev driver=$IMGFMT,file=backing-file,node-name=backing-fmt \ | ||
172 | + -blockdev driver=file,filename="$TEST_IMG",node-name=file \ | ||
173 | + -blockdev driver=$IMGFMT,file=file,backing=backing-fmt,node-name=fmt | | ||
174 | + _filter_date | ||
175 | + | ||
176 | +# This time, a snapshot should be created on both files | ||
177 | +echo Internal snapshots on overlay: | ||
178 | +$QEMU_IMG snapshot -l "$TEST_IMG" | _filter_date | ||
179 | + | ||
180 | +echo Internal snapshots on backing file: | ||
181 | +$QEMU_IMG snapshot -l "$TEST_IMG.base" | _filter_date | ||
182 | + | ||
183 | +# success, all done | ||
184 | +echo "*** done" | ||
185 | +rm -f $seq.full | ||
186 | +status=0 | ||
187 | diff --git a/tests/qemu-iotests/267.out b/tests/qemu-iotests/267.out | ||
188 | new file mode 100644 | ||
189 | index XXXXXXX..XXXXXXX | ||
190 | --- /dev/null | ||
191 | +++ b/tests/qemu-iotests/267.out | ||
192 | @@ -XXX,XX +XXX,XX @@ | ||
193 | +QA output created by 267 | ||
194 | + | ||
195 | +=== No block devices at all === | ||
196 | + | ||
197 | +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 | ||
198 | +Testing: | ||
199 | +QEMU X.Y.Z monitor - type 'help' for more information | ||
200 | +(qemu) savevm snap0 | ||
201 | +Error: No block device can accept snapshots | ||
202 | +(qemu) info snapshots | ||
203 | +No available block device supports snapshots | ||
204 | +(qemu) loadvm snap0 | ||
205 | +Error: No block device supports snapshots | ||
206 | +(qemu) quit | ||
207 | + | ||
208 | + | ||
209 | +=== -drive if=none === | ||
210 | + | ||
211 | +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 | ||
212 | +Testing: -drive driver=file,file=TEST_DIR/t.IMGFMT,if=none | ||
213 | +QEMU X.Y.Z monitor - type 'help' for more information | ||
214 | +(qemu) savevm snap0 | ||
215 | +Error: Device 'none0' is writable but does not support snapshots | ||
216 | +(qemu) info snapshots | ||
217 | +No available block device supports snapshots | ||
218 | +(qemu) loadvm snap0 | ||
219 | +Error: Device 'none0' is writable but does not support snapshots | ||
220 | +(qemu) quit | ||
221 | + | ||
222 | +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 | ||
223 | +Testing: -drive driver=IMGFMT,file=TEST_DIR/t.IMGFMT,if=none | ||
224 | +QEMU X.Y.Z monitor - type 'help' for more information | ||
225 | +(qemu) savevm snap0 | ||
226 | +(qemu) info snapshots | ||
227 | +List of snapshots present on all disks: | ||
228 | +ID TAG VM SIZE DATE VM CLOCK | ||
229 | +-- snap0 591 KiB yyyy-mm-dd hh:mm:ss 00:00:00.000 | ||
230 | +(qemu) loadvm snap0 | ||
231 | +(qemu) quit | ||
232 | + | ||
233 | +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 | ||
234 | +Testing: -drive driver=IMGFMT,file=TEST_DIR/t.IMGFMT,if=none -device virtio-blk,drive=none0 | ||
235 | +QEMU X.Y.Z monitor - type 'help' for more information | ||
236 | +(qemu) savevm snap0 | ||
237 | +(qemu) info snapshots | ||
238 | +List of snapshots present on all disks: | ||
239 | +ID TAG VM SIZE DATE VM CLOCK | ||
240 | +-- snap0 636 KiB yyyy-mm-dd hh:mm:ss 00:00:00.000 | ||
241 | +(qemu) loadvm snap0 | ||
242 | +(qemu) quit | ||
243 | + | ||
244 | + | ||
245 | +=== -drive if=virtio === | ||
246 | + | ||
247 | +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 | ||
248 | +Testing: -drive driver=file,file=TEST_DIR/t.IMGFMT,if=virtio | ||
249 | +QEMU X.Y.Z monitor - type 'help' for more information | ||
250 | +(qemu) savevm snap0 | ||
251 | +Error: Device 'virtio0' is writable but does not support snapshots | ||
252 | +(qemu) info snapshots | ||
253 | +No available block device supports snapshots | ||
254 | +(qemu) loadvm snap0 | ||
255 | +Error: Device 'virtio0' is writable but does not support snapshots | ||
256 | +(qemu) quit | ||
257 | + | ||
258 | +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 | ||
259 | +Testing: -drive driver=IMGFMT,file=TEST_DIR/t.IMGFMT,if=virtio | ||
260 | +QEMU X.Y.Z monitor - type 'help' for more information | ||
261 | +(qemu) savevm snap0 | ||
262 | +(qemu) info snapshots | ||
263 | +List of snapshots present on all disks: | ||
264 | +ID TAG VM SIZE DATE VM CLOCK | ||
265 | +-- snap0 636 KiB yyyy-mm-dd hh:mm:ss 00:00:00.000 | ||
266 | +(qemu) loadvm snap0 | ||
267 | +(qemu) quit | ||
268 | + | ||
269 | + | ||
270 | +=== Simple -blockdev === | ||
271 | + | ||
272 | +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 | ||
273 | +Testing: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=file | ||
274 | +QEMU X.Y.Z monitor - type 'help' for more information | ||
275 | +(qemu) savevm snap0 | ||
276 | +Error: Device '' is writable but does not support snapshots | ||
277 | +(qemu) info snapshots | ||
278 | +No available block device supports snapshots | ||
279 | +(qemu) loadvm snap0 | ||
280 | +Error: Device '' is writable but does not support snapshots | ||
281 | +(qemu) quit | ||
282 | + | ||
283 | +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 | ||
284 | +Testing: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=file -blockdev driver=IMGFMT,file=file,node-name=fmt | ||
285 | +QEMU X.Y.Z monitor - type 'help' for more information | ||
286 | +(qemu) savevm snap0 | ||
287 | +(qemu) info snapshots | ||
288 | +List of snapshots present on all disks: | ||
289 | +ID TAG VM SIZE DATE VM CLOCK | ||
290 | +-- snap0 591 KiB yyyy-mm-dd hh:mm:ss 00:00:00.000 | ||
291 | +(qemu) loadvm snap0 | ||
292 | +(qemu) quit | ||
293 | + | ||
294 | +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 | ||
295 | +Testing: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=file -blockdev driver=raw,file=file,node-name=raw -blockdev driver=IMGFMT,file=raw,node-name=fmt | ||
296 | +QEMU X.Y.Z monitor - type 'help' for more information | ||
297 | +(qemu) savevm snap0 | ||
298 | +(qemu) info snapshots | ||
299 | +List of snapshots present on all disks: | ||
300 | +ID TAG VM SIZE DATE VM CLOCK | ||
301 | +-- snap0 591 KiB yyyy-mm-dd hh:mm:ss 00:00:00.000 | ||
302 | +(qemu) loadvm snap0 | ||
303 | +(qemu) quit | ||
304 | + | ||
305 | + | ||
306 | +=== -blockdev with a filter on top === | ||
307 | + | ||
308 | +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 | ||
309 | +Testing: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=file -blockdev driver=IMGFMT,file=file,node-name=fmt -blockdev driver=copy-on-read,file=fmt,node-name=filter | ||
310 | +QEMU X.Y.Z monitor - type 'help' for more information | ||
311 | +(qemu) savevm snap0 | ||
312 | +(qemu) info snapshots | ||
313 | +List of snapshots present on all disks: | ||
314 | +ID TAG VM SIZE DATE VM CLOCK | ||
315 | +-- snap0 591 KiB yyyy-mm-dd hh:mm:ss 00:00:00.000 | ||
316 | +(qemu) loadvm snap0 | ||
317 | +(qemu) quit | ||
318 | + | ||
319 | + | ||
320 | +=== -blockdev with a backing file === | ||
321 | + | ||
322 | +Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=134217728 | ||
323 | +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/t.IMGFMT.base | ||
324 | +Testing: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT.base,node-name=backing-file -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=file -blockdev driver=IMGFMT,file=file,backing=backing-file,node-name=fmt | ||
325 | +QEMU X.Y.Z monitor - type 'help' for more information | ||
326 | +(qemu) savevm snap0 | ||
327 | +(qemu) info snapshots | ||
328 | +List of snapshots present on all disks: | ||
329 | +ID TAG VM SIZE DATE VM CLOCK | ||
330 | +-- snap0 591 KiB yyyy-mm-dd hh:mm:ss 00:00:00.000 | ||
331 | +(qemu) loadvm snap0 | ||
332 | +(qemu) quit | ||
333 | + | ||
334 | +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/t.IMGFMT.base | ||
335 | +Testing: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT.base,node-name=backing-file -blockdev driver=IMGFMT,file=backing-file,node-name=backing-fmt -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=file -blockdev driver=IMGFMT,file=file,backing=backing-fmt,node-name=fmt | ||
336 | +QEMU X.Y.Z monitor - type 'help' for more information | ||
337 | +(qemu) savevm snap0 | ||
338 | +(qemu) info snapshots | ||
339 | +List of snapshots present on all disks: | ||
340 | +ID TAG VM SIZE DATE VM CLOCK | ||
341 | +-- snap0 591 KiB yyyy-mm-dd hh:mm:ss 00:00:00.000 | ||
342 | +(qemu) loadvm snap0 | ||
343 | +(qemu) quit | ||
344 | + | ||
345 | +Internal snapshots on overlay: | ||
346 | +Snapshot list: | ||
347 | +ID TAG VM SIZE DATE VM CLOCK | ||
348 | +1 snap0 591 KiB yyyy-mm-dd hh:mm:ss 00:00:00.000 | ||
349 | +Internal snapshots on backing file: | ||
350 | + | ||
351 | +=== -blockdev with NBD server on the backing file === | ||
352 | + | ||
353 | +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/t.IMGFMT.base | ||
354 | +Testing: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT.base,node-name=backing-file -blockdev driver=IMGFMT,file=backing-file,node-name=backing-fmt -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=file -blockdev driver=IMGFMT,file=file,backing=backing-fmt,node-name=fmt | ||
355 | +QEMU X.Y.Z monitor - type 'help' for more information | ||
356 | +(qemu) nbd_server_start unix:TEST_DIR/nbd | ||
357 | +(qemu) nbd_server_add -w backing-fmt | ||
358 | +(qemu) savevm snap0 | ||
359 | +(qemu) info snapshots | ||
360 | +List of snapshots present on all disks: | ||
361 | +ID TAG VM SIZE DATE VM CLOCK | ||
362 | +-- snap0 591 KiB yyyy-mm-dd hh:mm:ss 00:00:00.000 | ||
363 | +(qemu) loadvm snap0 | ||
364 | +(qemu) quit | ||
365 | + | ||
366 | +Internal snapshots on overlay: | ||
367 | +Snapshot list: | ||
368 | +ID TAG VM SIZE DATE VM CLOCK | ||
369 | +1 snap0 0 B yyyy-mm-dd hh:mm:ss 00:00:00.000 | ||
370 | +Internal snapshots on backing file: | ||
371 | +Snapshot list: | ||
372 | +ID TAG VM SIZE DATE VM CLOCK | ||
373 | +1 snap0 591 KiB yyyy-mm-dd hh:mm:ss 00:00:00.000 | ||
374 | +*** done | ||
375 | diff --git a/tests/qemu-iotests/common.filter b/tests/qemu-iotests/common.filter | ||
376 | index XXXXXXX..XXXXXXX 100644 | 12 | index XXXXXXX..XXXXXXX 100644 |
377 | --- a/tests/qemu-iotests/common.filter | 13 | --- a/blockdev.c |
378 | +++ b/tests/qemu-iotests/common.filter | 14 | +++ b/blockdev.c |
379 | @@ -XXX,XX +XXX,XX @@ | 15 | @@ -XXX,XX +XXX,XX @@ void hmp_commit(Monitor *mon, const QDict *qdict) |
380 | # standard filters | 16 | |
381 | # | 17 | blk = blk_by_name(device); |
382 | 18 | if (!blk) { | |
383 | -# ctime(3) dates | 19 | - monitor_printf(mon, "Device '%s' not found\n", device); |
384 | -# | 20 | + error_report("Device '%s' not found", device); |
385 | _filter_date() | 21 | return; |
386 | { | 22 | } |
387 | - $SED \ | 23 | if (!blk_is_available(blk)) { |
388 | - -e 's/[A-Z][a-z][a-z] [A-z][a-z][a-z] *[0-9][0-9]* [0-9][0-9]:[0-9][0-9]:[0-9][0-9] [0-9][0-9][0-9][0-9]$/DATE/' | 24 | - monitor_printf(mon, "Device '%s' has no medium\n", device); |
389 | + $SED -re 's/[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}/yyyy-mm-dd hh:mm:ss/' | 25 | + error_report("Device '%s' has no medium", device); |
26 | return; | ||
27 | } | ||
28 | |||
29 | @@ -XXX,XX +XXX,XX @@ void hmp_commit(Monitor *mon, const QDict *qdict) | ||
30 | aio_context_release(aio_context); | ||
31 | } | ||
32 | if (ret < 0) { | ||
33 | - monitor_printf(mon, "'commit' error for '%s': %s\n", device, | ||
34 | - strerror(-ret)); | ||
35 | + error_report("'commit' error for '%s': %s", device, strerror(-ret)); | ||
36 | } | ||
390 | } | 37 | } |
391 | 38 | ||
392 | _filter_generated_node_ids() | ||
393 | diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group | ||
394 | index XXXXXXX..XXXXXXX 100644 | ||
395 | --- a/tests/qemu-iotests/group | ||
396 | +++ b/tests/qemu-iotests/group | ||
397 | @@ -XXX,XX +XXX,XX @@ | ||
398 | 263 rw quick | ||
399 | 265 rw auto quick | ||
400 | 266 rw quick | ||
401 | +267 rw auto quick snapshot | ||
402 | -- | 39 | -- |
403 | 2.20.1 | 40 | 2.20.1 |
404 | 41 | ||
405 | 42 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> | ||
1 | 2 | ||
3 | After commit 00e30f05de1d195, there is no more "goto error" points | ||
4 | after job creation, so after "error:" @job is always NULL and we don't | ||
5 | need roll-back job creation. | ||
6 | |||
7 | Reported-by: Coverity (CID 1406402) | ||
8 | Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> | ||
9 | Acked-by: Stefano Garzarella <sgarzare@redhat.com> | ||
10 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
11 | --- | ||
12 | block/backup.c | 5 +---- | ||
13 | 1 file changed, 1 insertion(+), 4 deletions(-) | ||
14 | |||
15 | diff --git a/block/backup.c b/block/backup.c | ||
16 | index XXXXXXX..XXXXXXX 100644 | ||
17 | --- a/block/backup.c | ||
18 | +++ b/block/backup.c | ||
19 | @@ -XXX,XX +XXX,XX @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs, | ||
20 | if (sync_bitmap) { | ||
21 | bdrv_reclaim_dirty_bitmap(sync_bitmap, NULL); | ||
22 | } | ||
23 | - if (job) { | ||
24 | - backup_clean(&job->common.job); | ||
25 | - job_early_fail(&job->common.job); | ||
26 | - } else if (backup_top) { | ||
27 | + if (backup_top) { | ||
28 | bdrv_backup_top_drop(backup_top); | ||
29 | } | ||
30 | |||
31 | -- | ||
32 | 2.20.1 | ||
33 | |||
34 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | We added more generic options after introducing -blockdev and forgot to | ||
2 | update the documentation (man page and --help output) accordingly. Do | ||
3 | that now. | ||
1 | 4 | ||
5 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
6 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> | ||
7 | --- | ||
8 | qemu-options.hx | 22 +++++++++++++++++++++- | ||
9 | 1 file changed, 21 insertions(+), 1 deletion(-) | ||
10 | |||
11 | diff --git a/qemu-options.hx b/qemu-options.hx | ||
12 | index XXXXXXX..XXXXXXX 100644 | ||
13 | --- a/qemu-options.hx | ||
14 | +++ b/qemu-options.hx | ||
15 | @@ -XXX,XX +XXX,XX @@ ETEXI | ||
16 | DEF("blockdev", HAS_ARG, QEMU_OPTION_blockdev, | ||
17 | "-blockdev [driver=]driver[,node-name=N][,discard=ignore|unmap]\n" | ||
18 | " [,cache.direct=on|off][,cache.no-flush=on|off]\n" | ||
19 | - " [,read-only=on|off][,detect-zeroes=on|off|unmap]\n" | ||
20 | + " [,read-only=on|off][,auto-read-only=on|off]\n" | ||
21 | + " [,force-share=on|off][,detect-zeroes=on|off|unmap]\n" | ||
22 | " [,driver specific parameters...]\n" | ||
23 | " configure a block backend\n", QEMU_ARCH_ALL) | ||
24 | STEXI | ||
25 | @@ -XXX,XX +XXX,XX @@ name is not intended to be predictable and changes between QEMU invocations. | ||
26 | For the top level, an explicit node name must be specified. | ||
27 | @item read-only | ||
28 | Open the node read-only. Guest write attempts will fail. | ||
29 | + | ||
30 | +Note that some block drivers support only read-only access, either generally or | ||
31 | +in certain configurations. In this case, the default value | ||
32 | +@option{read-only=off} does not work and the option must be specified | ||
33 | +explicitly. | ||
34 | +@item auto-read-only | ||
35 | +If @option{auto-read-only=on} is set, QEMU may fall back to read-only usage | ||
36 | +even when @option{read-only=off} is requested, or even switch between modes as | ||
37 | +needed, e.g. depending on whether the image file is writable or whether a | ||
38 | +writing user is attached to the node. | ||
39 | +@item force-share | ||
40 | +Override the image locking system of QEMU by forcing the node to utilize | ||
41 | +weaker shared access for permissions where it would normally request exclusive | ||
42 | +access. When there is the potential for multiple instances to have the same | ||
43 | +file open (whether this invocation of QEMU is the first or the second | ||
44 | +instance), both instances must permit shared access for the second instance to | ||
45 | +succeed at opening the file. | ||
46 | + | ||
47 | +Enabling @option{force-share=on} requires @option{read-only=on}. | ||
48 | @item cache.direct | ||
49 | The host page cache can be avoided with @option{cache.direct=on}. This will | ||
50 | attempt to do disk IO directly to the guest's memory. QEMU may still perform an | ||
51 | -- | ||
52 | 2.20.1 | ||
53 | |||
54 | diff view generated by jsdifflib |
1 | Nodes involved in internal snapshots were those that were returned by | 1 | Some functions require that the caller holds a certain CoMutex for them |
---|---|---|---|
2 | bdrv_next(), inserted and not read-only. bdrv_next() in turn returns all | 2 | to operate correctly. Add a function so that they can assert the lock is |
3 | nodes that are either the root node of a BlockBackend or monitor-owned | 3 | really held. |
4 | nodes. | ||
5 | |||
6 | With the typical -drive use, this worked well enough. However, in the | ||
7 | typical -blockdev case, the user defines one node per option, making all | ||
8 | nodes monitor-owned nodes. This includes protocol nodes etc. which often | ||
9 | are not snapshottable, so "savevm" only returns an error. | ||
10 | |||
11 | Change the conditions so that internal snapshot still include all nodes | ||
12 | that have a BlockBackend attached (we definitely want to snapshot | ||
13 | anything attached to a guest device and probably also the built-in NBD | ||
14 | server; snapshotting block job BlockBackends is more of an accident, but | ||
15 | a preexisting one), but other monitor-owned nodes are only included if | ||
16 | they have no parents. | ||
17 | |||
18 | This makes internal snapshots usable again with typical -blockdev | ||
19 | configurations. | ||
20 | 4 | ||
21 | Cc: qemu-stable@nongnu.org | 5 | Cc: qemu-stable@nongnu.org |
22 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | 6 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> |
23 | Reviewed-by: Eric Blake <eblake@redhat.com> | 7 | Tested-by: Michael Weiser <michael.weiser@gmx.de> |
24 | Reviewed-by: Peter Krempa <pkrempa@redhat.com> | 8 | Reviewed-by: Michael Weiser <michael.weiser@gmx.de> |
25 | Tested-by: Peter Krempa <pkrempa@redhat.com> | 9 | Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> |
10 | Reviewed-by: Denis V. Lunev <den@openvz.org> | ||
11 | Reviewed-by: Max Reitz <mreitz@redhat.com> | ||
26 | --- | 12 | --- |
27 | block/snapshot.c | 26 +++++++++++++++++++------- | 13 | include/qemu/coroutine.h | 15 +++++++++++++++ |
28 | 1 file changed, 19 insertions(+), 7 deletions(-) | 14 | 1 file changed, 15 insertions(+) |
29 | 15 | ||
30 | diff --git a/block/snapshot.c b/block/snapshot.c | 16 | diff --git a/include/qemu/coroutine.h b/include/qemu/coroutine.h |
31 | index XXXXXXX..XXXXXXX 100644 | 17 | index XXXXXXX..XXXXXXX 100644 |
32 | --- a/block/snapshot.c | 18 | --- a/include/qemu/coroutine.h |
33 | +++ b/block/snapshot.c | 19 | +++ b/include/qemu/coroutine.h |
34 | @@ -XXX,XX +XXX,XX @@ | 20 | @@ -XXX,XX +XXX,XX @@ void coroutine_fn qemu_co_mutex_lock(CoMutex *mutex); |
35 | #include "qapi/qmp/qerror.h" | 21 | */ |
36 | #include "qapi/qmp/qstring.h" | 22 | void coroutine_fn qemu_co_mutex_unlock(CoMutex *mutex); |
37 | #include "qemu/option.h" | 23 | |
38 | +#include "sysemu/block-backend.h" | 24 | +/** |
39 | 25 | + * Assert that the current coroutine holds @mutex. | |
40 | QemuOptsList internal_snapshot_opts = { | 26 | + */ |
41 | .name = "snapshot", | 27 | +static inline coroutine_fn void qemu_co_mutex_assert_locked(CoMutex *mutex) |
42 | @@ -XXX,XX +XXX,XX @@ int bdrv_snapshot_load_tmp_by_id_or_name(BlockDriverState *bs, | ||
43 | return ret; | ||
44 | } | ||
45 | |||
46 | +static bool bdrv_all_snapshots_includes_bs(BlockDriverState *bs) | ||
47 | +{ | 28 | +{ |
48 | + if (!bdrv_is_inserted(bs) || bdrv_is_read_only(bs)) { | 29 | + /* |
49 | + return false; | 30 | + * mutex->holder doesn't need any synchronisation if the assertion holds |
50 | + } | 31 | + * true because the mutex protects it. If it doesn't hold true, we still |
51 | + | 32 | + * don't mind if another thread takes or releases mutex behind our back, |
52 | + /* Include all nodes that are either in use by a BlockBackend, or that | 33 | + * because the condition will be false no matter whether we read NULL or |
53 | + * aren't attached to any node, but owned by the monitor. */ | 34 | + * the pointer for any other coroutine. |
54 | + return bdrv_has_blk(bs) || QLIST_EMPTY(&bs->parents); | 35 | + */ |
36 | + assert(atomic_read(&mutex->locked) && | ||
37 | + mutex->holder == qemu_coroutine_self()); | ||
55 | +} | 38 | +} |
56 | 39 | ||
57 | /* Group operations. All block drivers are involved. | 40 | /** |
58 | * These functions will properly handle dataplane (take aio_context_acquire | 41 | * CoQueues are a mechanism to queue coroutines in order to continue executing |
59 | @@ -XXX,XX +XXX,XX @@ bool bdrv_all_can_snapshot(BlockDriverState **first_bad_bs) | ||
60 | AioContext *ctx = bdrv_get_aio_context(bs); | ||
61 | |||
62 | aio_context_acquire(ctx); | ||
63 | - if (bdrv_is_inserted(bs) && !bdrv_is_read_only(bs)) { | ||
64 | + if (bdrv_all_snapshots_includes_bs(bs)) { | ||
65 | ok = bdrv_can_snapshot(bs); | ||
66 | } | ||
67 | aio_context_release(ctx); | ||
68 | @@ -XXX,XX +XXX,XX @@ int bdrv_all_delete_snapshot(const char *name, BlockDriverState **first_bad_bs, | ||
69 | AioContext *ctx = bdrv_get_aio_context(bs); | ||
70 | |||
71 | aio_context_acquire(ctx); | ||
72 | - if (bdrv_can_snapshot(bs) && | ||
73 | - bdrv_snapshot_find(bs, snapshot, name) >= 0) { | ||
74 | + if (bdrv_all_snapshots_includes_bs(bs) && | ||
75 | + bdrv_snapshot_find(bs, snapshot, name) >= 0) | ||
76 | + { | ||
77 | ret = bdrv_snapshot_delete(bs, snapshot->id_str, | ||
78 | snapshot->name, err); | ||
79 | } | ||
80 | @@ -XXX,XX +XXX,XX @@ int bdrv_all_goto_snapshot(const char *name, BlockDriverState **first_bad_bs, | ||
81 | AioContext *ctx = bdrv_get_aio_context(bs); | ||
82 | |||
83 | aio_context_acquire(ctx); | ||
84 | - if (bdrv_can_snapshot(bs)) { | ||
85 | + if (bdrv_all_snapshots_includes_bs(bs)) { | ||
86 | ret = bdrv_snapshot_goto(bs, name, errp); | ||
87 | } | ||
88 | aio_context_release(ctx); | ||
89 | @@ -XXX,XX +XXX,XX @@ int bdrv_all_find_snapshot(const char *name, BlockDriverState **first_bad_bs) | ||
90 | AioContext *ctx = bdrv_get_aio_context(bs); | ||
91 | |||
92 | aio_context_acquire(ctx); | ||
93 | - if (bdrv_can_snapshot(bs)) { | ||
94 | + if (bdrv_all_snapshots_includes_bs(bs)) { | ||
95 | err = bdrv_snapshot_find(bs, &sn, name); | ||
96 | } | ||
97 | aio_context_release(ctx); | ||
98 | @@ -XXX,XX +XXX,XX @@ int bdrv_all_create_snapshot(QEMUSnapshotInfo *sn, | ||
99 | if (bs == vm_state_bs) { | ||
100 | sn->vm_state_size = vm_state_size; | ||
101 | err = bdrv_snapshot_create(bs, sn); | ||
102 | - } else if (bdrv_can_snapshot(bs)) { | ||
103 | + } else if (bdrv_all_snapshots_includes_bs(bs)) { | ||
104 | sn->vm_state_size = 0; | ||
105 | err = bdrv_snapshot_create(bs, sn); | ||
106 | } | ||
107 | @@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_all_find_vmstate_bs(void) | ||
108 | bool found; | ||
109 | |||
110 | aio_context_acquire(ctx); | ||
111 | - found = bdrv_can_snapshot(bs); | ||
112 | + found = bdrv_all_snapshots_includes_bs(bs) && bdrv_can_snapshot(bs); | ||
113 | aio_context_release(ctx); | ||
114 | |||
115 | if (found) { | ||
116 | -- | 42 | -- |
117 | 2.20.1 | 43 | 2.20.1 |
118 | 44 | ||
119 | 45 | diff view generated by jsdifflib |
1 | Running iotests is not required to build QEMU, so we can have stricter | 1 | qcow2_detect_metadata_preallocation() calls qcow2_get_refcount() which |
---|---|---|---|
2 | version requirements for Python here and can make use of new features | 2 | requires s->lock to be taken to protect its accesses to the refcount |
3 | and drop compatibility code earlier. | 3 | table and refcount blocks. However, nothing in this code path actually |
4 | took the lock. This could cause the same cache entry to be used by two | ||
5 | requests at the same time, for different tables at different offsets, | ||
6 | resulting in image corruption. | ||
4 | 7 | ||
5 | This makes qemu-iotests skip all Python tests if a Python version before | 8 | As it would be preferable to base the detection on consistent data (even |
6 | 3.6 is used for the build. | 9 | though it's just heuristics), let's take the lock not only around the |
10 | qcow2_get_refcount() calls, but around the whole function. | ||
7 | 11 | ||
8 | Suggested-by: Eduardo Habkost <ehabkost@redhat.com> | 12 | This patch takes the lock in qcow2_co_block_status() earlier and asserts |
13 | in qcow2_detect_metadata_preallocation() that we hold the lock. | ||
14 | |||
15 | Fixes: 69f47505ee66afaa513305de0c1895a224e52c45 | ||
16 | Cc: qemu-stable@nongnu.org | ||
17 | Reported-by: Michael Weiser <michael.weiser@gmx.de> | ||
9 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | 18 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> |
10 | Reviewed-by: Eduardo Habkost <ehabkost@redhat.com> | 19 | Tested-by: Michael Weiser <michael.weiser@gmx.de> |
11 | Reviewed-by: Thomas Huth <thuth@redhat.com> | 20 | Reviewed-by: Michael Weiser <michael.weiser@gmx.de> |
12 | Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com> | ||
13 | Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> | 21 | Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> |
22 | Reviewed-by: Max Reitz <mreitz@redhat.com> | ||
14 | --- | 23 | --- |
15 | tests/qemu-iotests/check | 13 ++++++++++++- | 24 | block/qcow2-refcount.c | 2 ++ |
16 | 1 file changed, 12 insertions(+), 1 deletion(-) | 25 | block/qcow2.c | 3 ++- |
26 | 2 files changed, 4 insertions(+), 1 deletion(-) | ||
17 | 27 | ||
18 | diff --git a/tests/qemu-iotests/check b/tests/qemu-iotests/check | 28 | diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c |
19 | index XXXXXXX..XXXXXXX 100755 | 29 | index XXXXXXX..XXXXXXX 100644 |
20 | --- a/tests/qemu-iotests/check | 30 | --- a/block/qcow2-refcount.c |
21 | +++ b/tests/qemu-iotests/check | 31 | +++ b/block/qcow2-refcount.c |
22 | @@ -XXX,XX +XXX,XX @@ then | 32 | @@ -XXX,XX +XXX,XX @@ int qcow2_detect_metadata_preallocation(BlockDriverState *bs) |
23 | export SOCKET_SCM_HELPER="$build_iotests/socket_scm_helper" | 33 | int64_t i, end_cluster, cluster_count = 0, threshold; |
24 | fi | 34 | int64_t file_length, real_allocation, real_clusters; |
25 | 35 | ||
26 | +python_usable=false | 36 | + qemu_co_mutex_assert_locked(&s->lock); |
27 | +if $PYTHON -c 'import sys; sys.exit(0 if sys.version_info >= (3,6) else 1)' | ||
28 | +then | ||
29 | + python_usable=true | ||
30 | +fi | ||
31 | + | 37 | + |
32 | default_machine=$($QEMU_PROG -machine help | sed -n '/(default)/ s/ .*//p') | 38 | file_length = bdrv_getlength(bs->file->bs); |
33 | default_alias_machine=$($QEMU_PROG -machine help | \ | 39 | if (file_length < 0) { |
34 | sed -n "/(alias of $default_machine)/ { s/ .*//p; q; }") | 40 | return file_length; |
35 | @@ -XXX,XX +XXX,XX @@ do | 41 | diff --git a/block/qcow2.c b/block/qcow2.c |
36 | start=$(_wallclock) | 42 | index XXXXXXX..XXXXXXX 100644 |
37 | 43 | --- a/block/qcow2.c | |
38 | if [ "$(head -n 1 "$source_iotests/$seq")" == "#!/usr/bin/env python" ]; then | 44 | +++ b/block/qcow2.c |
39 | - run_command="$PYTHON $seq" | 45 | @@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_block_status(BlockDriverState *bs, |
40 | + if $python_usable; then | 46 | unsigned int bytes; |
41 | + run_command="$PYTHON $seq" | 47 | int status = 0; |
42 | + else | 48 | |
43 | + run_command="false" | 49 | + qemu_co_mutex_lock(&s->lock); |
44 | + echo "Unsupported Python version" > $seq.notrun | 50 | + |
45 | + fi | 51 | if (!s->metadata_preallocation_checked) { |
46 | else | 52 | ret = qcow2_detect_metadata_preallocation(bs); |
47 | run_command="./$seq" | 53 | s->metadata_preallocation = (ret == 1); |
48 | fi | 54 | @@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_block_status(BlockDriverState *bs, |
55 | } | ||
56 | |||
57 | bytes = MIN(INT_MAX, count); | ||
58 | - qemu_co_mutex_lock(&s->lock); | ||
59 | ret = qcow2_get_cluster_offset(bs, offset, &bytes, &cluster_offset); | ||
60 | qemu_co_mutex_unlock(&s->lock); | ||
61 | if (ret < 0) { | ||
49 | -- | 62 | -- |
50 | 2.20.1 | 63 | 2.20.1 |
51 | 64 | ||
52 | 65 | diff view generated by jsdifflib |