1 | The following changes since commit 2d2c73d0e3d504a61f868e46e6abd5643f38091b: | 1 | The following changes since commit 99fc08366b06282614daeda989d2fde6ab8a707f: |
---|---|---|---|
2 | 2 | ||
3 | Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20200914-1' into staging (2020-09-14 16:03:08 +0100) | 3 | Merge tag 'seabios-20211203-pull-request' of git://git.kraxel.org/qemu into staging (2021-12-03 05:26:40 -0800) |
4 | 4 | ||
5 | are available in the Git repository at: | 5 | are available in the Git repository at: |
6 | 6 | ||
7 | https://github.com/XanClic/qemu.git tags/pull-block-2020-09-15 | 7 | https://gitlab.com/stefanha/qemu.git tags/block-pull-request |
8 | 8 | ||
9 | for you to fetch changes up to 7bae7c805d82675eb3a02c744093703d84ada2d6: | 9 | for you to fetch changes up to 5b807181c27a940a3a7ad1f221a2e76a132cbdc0: |
10 | 10 | ||
11 | block/rbd: add 'namespace' to qemu_rbd_strong_runtime_opts[] (2020-09-15 11:31:10 +0200) | 11 | virtio-blk: Fix clean up of host notifiers for single MR transaction. (2021-12-06 14:21:14 +0000) |
12 | 12 | ||
13 | ---------------------------------------------------------------- | 13 | ---------------------------------------------------------------- |
14 | Block patches: | 14 | Pull request |
15 | - Several qcow2 fixes and refactorings | ||
16 | - Let qemu-img convert try to stay at cluster boundaries | ||
17 | - Stable child names for quorum (with x-blockdev-change) | ||
18 | - Explicitly drop vhdx 4k sector support, as it was never actually | ||
19 | working | ||
20 | - rbd: Mark @namespace a strong runtime option | ||
21 | - iotests.py improvements | ||
22 | - Drop unused runtime_opts objects | ||
23 | - Skip a test case in 030 when run through make check-block | ||
24 | 15 | ||
25 | ---------------------------------------------------------------- | 16 | ---------------------------------------------------------------- |
26 | Alberto Garcia (9): | ||
27 | qcow2: Use macros for the L1, refcount and bitmap table entry sizes | ||
28 | qcow2: Fix removal of list members from BDRVQcow2State.cluster_allocs | ||
29 | qcow2: Don't check nb_clusters when removing l2meta from the list | ||
30 | qcow2: Rewrite the documentation of qcow2_alloc_cluster_offset() | ||
31 | qcow2: Handle QCowL2Meta on error in preallocate_co() | ||
32 | qcow2: Make qcow2_free_any_clusters() free only one cluster | ||
33 | qcow2: Return the original error code in qcow2_co_pwrite_zeroes() | ||
34 | qcow2: Make preallocate_co() resize the image to the correct size | ||
35 | qcow2: Convert qcow2_alloc_cluster_offset() into | ||
36 | qcow2_alloc_host_offset() | ||
37 | 17 | ||
38 | John Snow (2): | 18 | Mark Mielke (1): |
39 | block/rbd: remove runtime_opts | 19 | virtio-blk: Fix clean up of host notifiers for single MR transaction. |
40 | block/qcow: remove runtime opts | ||
41 | 20 | ||
42 | Lukas Straub (1): | 21 | hw/block/dataplane/virtio-blk.c | 2 +- |
43 | block/quorum.c: stable children names | 22 | 1 file changed, 1 insertion(+), 1 deletion(-) |
44 | |||
45 | Nir Soffer (5): | ||
46 | qemu-iotests: Fix FilePaths cleanup | ||
47 | qemu-iotests: Fix FilePaths docstring | ||
48 | qemu-iotests: Support varargs syntax in FilePaths | ||
49 | qemu-iotests: Merge FilePaths and FilePath | ||
50 | qemu-iotests: Simplify FilePath __init__ | ||
51 | |||
52 | Peter Lieven (1): | ||
53 | qemu-img: avoid unaligned read requests during convert | ||
54 | |||
55 | Stefano Garzarella (1): | ||
56 | block/rbd: add 'namespace' to qemu_rbd_strong_runtime_opts[] | ||
57 | |||
58 | Swapnil Ingle (1): | ||
59 | block/vhdx: Support vhdx image only with 512 bytes logical sector size | ||
60 | |||
61 | Thomas Huth (1): | ||
62 | iotests: Skip test_stream_parallel in test 030 when doing "make check" | ||
63 | |||
64 | Yi Li (1): | ||
65 | qemu-img: Explicit number replaced by a constant | ||
66 | |||
67 | block/qcow2.h | 16 +++-- | ||
68 | block/qcow.c | 9 --- | ||
69 | block/qcow2-bitmap.c | 11 ++-- | ||
70 | block/qcow2-cluster.c | 69 ++++++++++++---------- | ||
71 | block/qcow2-refcount.c | 97 +++++++++++++++--------------- | ||
72 | block/qcow2-snapshot.c | 20 +++---- | ||
73 | block/qcow2.c | 108 ++++++++++++++-------------------- | ||
74 | block/quorum.c | 20 +++++-- | ||
75 | block/rbd.c | 43 +------------- | ||
76 | block/vhdx.c | 6 +- | ||
77 | qemu-img.c | 32 ++++++++-- | ||
78 | tests/check-block.sh | 3 + | ||
79 | tests/qemu-iotests/030 | 2 + | ||
80 | tests/qemu-iotests/125 | 44 ++++++++------ | ||
81 | tests/qemu-iotests/125.out | 28 ++++++++- | ||
82 | tests/qemu-iotests/194 | 4 +- | ||
83 | tests/qemu-iotests/208 | 2 +- | ||
84 | tests/qemu-iotests/222 | 2 +- | ||
85 | tests/qemu-iotests/251 | 7 ++- | ||
86 | tests/qemu-iotests/257 | 10 ++-- | ||
87 | tests/qemu-iotests/305 | 74 +++++++++++++++++++++++ | ||
88 | tests/qemu-iotests/305.out | 16 +++++ | ||
89 | tests/qemu-iotests/group | 1 + | ||
90 | tests/qemu-iotests/iotests.py | 53 +++++++++-------- | ||
91 | 24 files changed, 395 insertions(+), 282 deletions(-) | ||
92 | create mode 100755 tests/qemu-iotests/305 | ||
93 | create mode 100644 tests/qemu-iotests/305.out | ||
94 | 23 | ||
95 | -- | 24 | -- |
96 | 2.26.2 | 25 | 2.33.1 |
97 | 26 | ||
98 | 27 | ||
28 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | From: Nir Soffer <nirsof@gmail.com> | ||
2 | 1 | ||
3 | If os.remove() fails to remove one of the paths, for example if the file | ||
4 | was removed by the test, the cleanup loop would exit silently, without | ||
5 | removing the rest of the files. | ||
6 | |||
7 | Fixes: de263986b5dc | ||
8 | Signed-off-by: Nir Soffer <nsoffer@redhat.com> | ||
9 | Reviewed-by: Max Reitz <mreitz@redhat.com> | ||
10 | Message-Id: <20200828232152.205833-2-nsoffer@redhat.com> | ||
11 | Signed-off-by: Max Reitz <mreitz@redhat.com> | ||
12 | --- | ||
13 | tests/qemu-iotests/iotests.py | 8 ++++---- | ||
14 | 1 file changed, 4 insertions(+), 4 deletions(-) | ||
15 | |||
16 | diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py | ||
17 | index XXXXXXX..XXXXXXX 100644 | ||
18 | --- a/tests/qemu-iotests/iotests.py | ||
19 | +++ b/tests/qemu-iotests/iotests.py | ||
20 | @@ -XXX,XX +XXX,XX @@ class FilePaths: | ||
21 | return self.paths | ||
22 | |||
23 | def __exit__(self, exc_type, exc_val, exc_tb): | ||
24 | - try: | ||
25 | - for path in self.paths: | ||
26 | + for path in self.paths: | ||
27 | + try: | ||
28 | os.remove(path) | ||
29 | - except OSError: | ||
30 | - pass | ||
31 | + except OSError: | ||
32 | + pass | ||
33 | return False | ||
34 | |||
35 | class FilePath(FilePaths): | ||
36 | -- | ||
37 | 2.26.2 | ||
38 | |||
39 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | From: Nir Soffer <nirsof@gmail.com> | ||
2 | 1 | ||
3 | When this class was extracted from FilePath, the docstring was not | ||
4 | updated for generating multiple files, and the example usage was | ||
5 | referencing unrelated file. | ||
6 | |||
7 | While fixing the docstring, add example for creating sockets, which | ||
8 | should use iotests.sock_dir instead of the default base_dir. | ||
9 | |||
10 | Fixes: de263986b5dc | ||
11 | Signed-off-by: Nir Soffer <nsoffer@redhat.com> | ||
12 | Message-Id: <20200828232152.205833-3-nsoffer@redhat.com> | ||
13 | Signed-off-by: Max Reitz <mreitz@redhat.com> | ||
14 | --- | ||
15 | tests/qemu-iotests/iotests.py | 19 +++++++++++++------ | ||
16 | 1 file changed, 13 insertions(+), 6 deletions(-) | ||
17 | |||
18 | diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py | ||
19 | index XXXXXXX..XXXXXXX 100644 | ||
20 | --- a/tests/qemu-iotests/iotests.py | ||
21 | +++ b/tests/qemu-iotests/iotests.py | ||
22 | @@ -XXX,XX +XXX,XX @@ def file_pattern(name): | ||
23 | |||
24 | class FilePaths: | ||
25 | """ | ||
26 | - FilePaths is an auto-generated filename that cleans itself up. | ||
27 | + Context manager generating multiple file names. The generated files are | ||
28 | + removed when exiting the context. | ||
29 | |||
30 | - Use this context manager to generate filenames and ensure that the file | ||
31 | - gets deleted:: | ||
32 | + Example usage: | ||
33 | + | ||
34 | + with FilePaths(['a.img', 'b.img']) as (img_a, img_b): | ||
35 | + # Use img_a and img_b here... | ||
36 | + | ||
37 | + # a.img and b.img are automatically removed here. | ||
38 | + | ||
39 | + By default images are created in iotests.test_dir. To create sockets use | ||
40 | + iotests.sock_dir: | ||
41 | + | ||
42 | + with FilePaths(['a.sock'], base_dir=iotests.sock_dir) as (sock,): | ||
43 | |||
44 | - with FilePaths(['test.img']) as img_path: | ||
45 | - qemu_img('create', img_path, '1G') | ||
46 | - # migration_sock_path is automatically deleted | ||
47 | """ | ||
48 | def __init__(self, names, base_dir=test_dir): | ||
49 | self.paths = [] | ||
50 | -- | ||
51 | 2.26.2 | ||
52 | |||
53 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | From: Nir Soffer <nirsof@gmail.com> | ||
2 | 1 | ||
3 | Accept variable number of names instead of a sequence: | ||
4 | |||
5 | with FilePaths("a", "b", "c") as (a, b, c): | ||
6 | |||
7 | The disadvantage is that base_dir must be used as kwarg: | ||
8 | |||
9 | with FilePaths("a", "b", base_dir=soc_dir) as (sock1, sock2): | ||
10 | |||
11 | But this is more clear and calling optional argument as positional | ||
12 | arguments is bad idea anyway. | ||
13 | |||
14 | Signed-off-by: Nir Soffer <nsoffer@redhat.com> | ||
15 | Reviewed-by: Max Reitz <mreitz@redhat.com> | ||
16 | Message-Id: <20200828232152.205833-4-nsoffer@redhat.com> | ||
17 | Signed-off-by: Max Reitz <mreitz@redhat.com> | ||
18 | --- | ||
19 | tests/qemu-iotests/194 | 4 ++-- | ||
20 | tests/qemu-iotests/257 | 10 ++++------ | ||
21 | tests/qemu-iotests/iotests.py | 8 ++++---- | ||
22 | 3 files changed, 10 insertions(+), 12 deletions(-) | ||
23 | |||
24 | diff --git a/tests/qemu-iotests/194 b/tests/qemu-iotests/194 | ||
25 | index XXXXXXX..XXXXXXX 100755 | ||
26 | --- a/tests/qemu-iotests/194 | ||
27 | +++ b/tests/qemu-iotests/194 | ||
28 | @@ -XXX,XX +XXX,XX @@ iotests.script_initialize(supported_fmts=['qcow2', 'qed', 'raw'], | ||
29 | |||
30 | with iotests.FilePath('source.img') as source_img_path, \ | ||
31 | iotests.FilePath('dest.img') as dest_img_path, \ | ||
32 | - iotests.FilePaths(['migration.sock', 'nbd.sock'], iotests.sock_dir) as \ | ||
33 | - [migration_sock_path, nbd_sock_path], \ | ||
34 | + iotests.FilePaths('migration.sock', 'nbd.sock', base_dir=iotests.sock_dir) \ | ||
35 | + as (migration_sock_path, nbd_sock_path), \ | ||
36 | iotests.VM('source') as source_vm, \ | ||
37 | iotests.VM('dest') as dest_vm: | ||
38 | |||
39 | diff --git a/tests/qemu-iotests/257 b/tests/qemu-iotests/257 | ||
40 | index XXXXXXX..XXXXXXX 100755 | ||
41 | --- a/tests/qemu-iotests/257 | ||
42 | +++ b/tests/qemu-iotests/257 | ||
43 | @@ -XXX,XX +XXX,XX @@ def test_bitmap_sync(bsync_mode, msync_mode='bitmap', failure=None): | ||
44 | an incomplete backup. Testing limitations prevent | ||
45 | testing competing writes. | ||
46 | """ | ||
47 | - with iotests.FilePaths(['img', 'bsync1', 'bsync2', | ||
48 | - 'fbackup0', 'fbackup1', 'fbackup2']) as \ | ||
49 | - (img_path, bsync1, bsync2, | ||
50 | - fbackup0, fbackup1, fbackup2), \ | ||
51 | + with iotests.FilePaths( | ||
52 | + 'img', 'bsync1', 'bsync2', 'fbackup0', 'fbackup1', 'fbackup2') as \ | ||
53 | + (img_path, bsync1, bsync2, fbackup0, fbackup1, fbackup2), \ | ||
54 | iotests.VM() as vm: | ||
55 | |||
56 | mode = "Mode {:s}; Bitmap Sync {:s}".format(msync_mode, bsync_mode) | ||
57 | @@ -XXX,XX +XXX,XX @@ def test_backup_api(): | ||
58 | """ | ||
59 | Test malformed and prohibited invocations of the backup API. | ||
60 | """ | ||
61 | - with iotests.FilePaths(['img', 'bsync1']) as \ | ||
62 | - (img_path, backup_path), \ | ||
63 | + with iotests.FilePaths('img', 'bsync1') as (img_path, backup_path), \ | ||
64 | iotests.VM() as vm: | ||
65 | |||
66 | log("\n=== API failure tests ===\n") | ||
67 | diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py | ||
68 | index XXXXXXX..XXXXXXX 100644 | ||
69 | --- a/tests/qemu-iotests/iotests.py | ||
70 | +++ b/tests/qemu-iotests/iotests.py | ||
71 | @@ -XXX,XX +XXX,XX @@ class FilePaths: | ||
72 | |||
73 | Example usage: | ||
74 | |||
75 | - with FilePaths(['a.img', 'b.img']) as (img_a, img_b): | ||
76 | + with FilePaths('a.img', 'b.img') as (img_a, img_b): | ||
77 | # Use img_a and img_b here... | ||
78 | |||
79 | # a.img and b.img are automatically removed here. | ||
80 | @@ -XXX,XX +XXX,XX @@ class FilePaths: | ||
81 | By default images are created in iotests.test_dir. To create sockets use | ||
82 | iotests.sock_dir: | ||
83 | |||
84 | - with FilePaths(['a.sock'], base_dir=iotests.sock_dir) as (sock,): | ||
85 | + with FilePaths('a.sock', base_dir=iotests.sock_dir) as (sock,): | ||
86 | |||
87 | """ | ||
88 | - def __init__(self, names, base_dir=test_dir): | ||
89 | + def __init__(self, *names, base_dir=test_dir): | ||
90 | self.paths = [] | ||
91 | for name in names: | ||
92 | self.paths.append(os.path.join(base_dir, file_pattern(name))) | ||
93 | @@ -XXX,XX +XXX,XX @@ class FilePath(FilePaths): | ||
94 | FilePath is a specialization of FilePaths that takes a single filename. | ||
95 | """ | ||
96 | def __init__(self, name, base_dir=test_dir): | ||
97 | - super(FilePath, self).__init__([name], base_dir) | ||
98 | + super(FilePath, self).__init__(name, base_dir=base_dir) | ||
99 | |||
100 | def __enter__(self): | ||
101 | return self.paths[0] | ||
102 | -- | ||
103 | 2.26.2 | ||
104 | |||
105 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | From: Nir Soffer <nirsof@gmail.com> | ||
2 | 1 | ||
3 | FilePath creates now one temporary file: | ||
4 | |||
5 | with FilePath("a") as a: | ||
6 | |||
7 | Or more: | ||
8 | |||
9 | with FilePath("a", "b", "c") as (a, b, c): | ||
10 | |||
11 | This is also the behavior of the file_path() helper, used by some of the | ||
12 | tests. Now we have only 2 helpers for creating temporary files instead | ||
13 | of 3. | ||
14 | |||
15 | Signed-off-by: Nir Soffer <nsoffer@redhat.com> | ||
16 | Reviewed-by: Max Reitz <mreitz@redhat.com> | ||
17 | Message-Id: <20200828232152.205833-5-nsoffer@redhat.com> | ||
18 | Signed-off-by: Max Reitz <mreitz@redhat.com> | ||
19 | --- | ||
20 | tests/qemu-iotests/194 | 2 +- | ||
21 | tests/qemu-iotests/208 | 2 +- | ||
22 | tests/qemu-iotests/222 | 2 +- | ||
23 | tests/qemu-iotests/257 | 4 ++-- | ||
24 | tests/qemu-iotests/iotests.py | 23 ++++++++++------------- | ||
25 | 5 files changed, 15 insertions(+), 18 deletions(-) | ||
26 | |||
27 | diff --git a/tests/qemu-iotests/194 b/tests/qemu-iotests/194 | ||
28 | index XXXXXXX..XXXXXXX 100755 | ||
29 | --- a/tests/qemu-iotests/194 | ||
30 | +++ b/tests/qemu-iotests/194 | ||
31 | @@ -XXX,XX +XXX,XX @@ iotests.script_initialize(supported_fmts=['qcow2', 'qed', 'raw'], | ||
32 | |||
33 | with iotests.FilePath('source.img') as source_img_path, \ | ||
34 | iotests.FilePath('dest.img') as dest_img_path, \ | ||
35 | - iotests.FilePaths('migration.sock', 'nbd.sock', base_dir=iotests.sock_dir) \ | ||
36 | + iotests.FilePath('migration.sock', 'nbd.sock', base_dir=iotests.sock_dir) \ | ||
37 | as (migration_sock_path, nbd_sock_path), \ | ||
38 | iotests.VM('source') as source_vm, \ | ||
39 | iotests.VM('dest') as dest_vm: | ||
40 | diff --git a/tests/qemu-iotests/208 b/tests/qemu-iotests/208 | ||
41 | index XXXXXXX..XXXXXXX 100755 | ||
42 | --- a/tests/qemu-iotests/208 | ||
43 | +++ b/tests/qemu-iotests/208 | ||
44 | @@ -XXX,XX +XXX,XX @@ iotests.script_initialize(supported_fmts=['generic']) | ||
45 | |||
46 | with iotests.FilePath('disk.img') as disk_img_path, \ | ||
47 | iotests.FilePath('disk-snapshot.img') as disk_snapshot_img_path, \ | ||
48 | - iotests.FilePath('nbd.sock', iotests.sock_dir) as nbd_sock_path, \ | ||
49 | + iotests.FilePath('nbd.sock', base_dir=iotests.sock_dir) as nbd_sock_path, \ | ||
50 | iotests.VM() as vm: | ||
51 | |||
52 | img_size = '10M' | ||
53 | diff --git a/tests/qemu-iotests/222 b/tests/qemu-iotests/222 | ||
54 | index XXXXXXX..XXXXXXX 100755 | ||
55 | --- a/tests/qemu-iotests/222 | ||
56 | +++ b/tests/qemu-iotests/222 | ||
57 | @@ -XXX,XX +XXX,XX @@ remainder = [("0xd5", "0x108000", "32k"), # Right-end of partial-left [1] | ||
58 | |||
59 | with iotests.FilePath('base.img') as base_img_path, \ | ||
60 | iotests.FilePath('fleece.img') as fleece_img_path, \ | ||
61 | - iotests.FilePath('nbd.sock', iotests.sock_dir) as nbd_sock_path, \ | ||
62 | + iotests.FilePath('nbd.sock', base_dir=iotests.sock_dir) as nbd_sock_path, \ | ||
63 | iotests.VM() as vm: | ||
64 | |||
65 | log('--- Setting up images ---') | ||
66 | diff --git a/tests/qemu-iotests/257 b/tests/qemu-iotests/257 | ||
67 | index XXXXXXX..XXXXXXX 100755 | ||
68 | --- a/tests/qemu-iotests/257 | ||
69 | +++ b/tests/qemu-iotests/257 | ||
70 | @@ -XXX,XX +XXX,XX @@ def test_bitmap_sync(bsync_mode, msync_mode='bitmap', failure=None): | ||
71 | an incomplete backup. Testing limitations prevent | ||
72 | testing competing writes. | ||
73 | """ | ||
74 | - with iotests.FilePaths( | ||
75 | + with iotests.FilePath( | ||
76 | 'img', 'bsync1', 'bsync2', 'fbackup0', 'fbackup1', 'fbackup2') as \ | ||
77 | (img_path, bsync1, bsync2, fbackup0, fbackup1, fbackup2), \ | ||
78 | iotests.VM() as vm: | ||
79 | @@ -XXX,XX +XXX,XX @@ def test_backup_api(): | ||
80 | """ | ||
81 | Test malformed and prohibited invocations of the backup API. | ||
82 | """ | ||
83 | - with iotests.FilePaths('img', 'bsync1') as (img_path, backup_path), \ | ||
84 | + with iotests.FilePath('img', 'bsync1') as (img_path, backup_path), \ | ||
85 | iotests.VM() as vm: | ||
86 | |||
87 | log("\n=== API failure tests ===\n") | ||
88 | diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py | ||
89 | index XXXXXXX..XXXXXXX 100644 | ||
90 | --- a/tests/qemu-iotests/iotests.py | ||
91 | +++ b/tests/qemu-iotests/iotests.py | ||
92 | @@ -XXX,XX +XXX,XX @@ class Timeout: | ||
93 | def file_pattern(name): | ||
94 | return "{0}-{1}".format(os.getpid(), name) | ||
95 | |||
96 | -class FilePaths: | ||
97 | +class FilePath: | ||
98 | """ | ||
99 | Context manager generating multiple file names. The generated files are | ||
100 | removed when exiting the context. | ||
101 | |||
102 | Example usage: | ||
103 | |||
104 | - with FilePaths('a.img', 'b.img') as (img_a, img_b): | ||
105 | + with FilePath('a.img', 'b.img') as (img_a, img_b): | ||
106 | # Use img_a and img_b here... | ||
107 | |||
108 | # a.img and b.img are automatically removed here. | ||
109 | @@ -XXX,XX +XXX,XX @@ class FilePaths: | ||
110 | By default images are created in iotests.test_dir. To create sockets use | ||
111 | iotests.sock_dir: | ||
112 | |||
113 | - with FilePaths('a.sock', base_dir=iotests.sock_dir) as (sock,): | ||
114 | + with FilePath('a.sock', base_dir=iotests.sock_dir) as sock: | ||
115 | + | ||
116 | + For convenience, calling with one argument yields a single file instead of | ||
117 | + a tuple with one item. | ||
118 | |||
119 | """ | ||
120 | def __init__(self, *names, base_dir=test_dir): | ||
121 | @@ -XXX,XX +XXX,XX @@ class FilePaths: | ||
122 | self.paths.append(os.path.join(base_dir, file_pattern(name))) | ||
123 | |||
124 | def __enter__(self): | ||
125 | - return self.paths | ||
126 | + if len(self.paths) == 1: | ||
127 | + return self.paths[0] | ||
128 | + else: | ||
129 | + return self.paths | ||
130 | |||
131 | def __exit__(self, exc_type, exc_val, exc_tb): | ||
132 | for path in self.paths: | ||
133 | @@ -XXX,XX +XXX,XX @@ class FilePaths: | ||
134 | pass | ||
135 | return False | ||
136 | |||
137 | -class FilePath(FilePaths): | ||
138 | - """ | ||
139 | - FilePath is a specialization of FilePaths that takes a single filename. | ||
140 | - """ | ||
141 | - def __init__(self, name, base_dir=test_dir): | ||
142 | - super(FilePath, self).__init__(name, base_dir=base_dir) | ||
143 | - | ||
144 | - def __enter__(self): | ||
145 | - return self.paths[0] | ||
146 | |||
147 | def file_path_remover(): | ||
148 | for path in reversed(file_path_remover.paths): | ||
149 | -- | ||
150 | 2.26.2 | ||
151 | |||
152 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | From: Nir Soffer <nirsof@gmail.com> | ||
2 | 1 | ||
3 | Use list comprehension instead of append loop. | ||
4 | |||
5 | Signed-off-by: Nir Soffer <nsoffer@redhat.com> | ||
6 | Reviewed-by: Max Reitz <mreitz@redhat.com> | ||
7 | Message-Id: <20200828232152.205833-6-nsoffer@redhat.com> | ||
8 | Signed-off-by: Max Reitz <mreitz@redhat.com> | ||
9 | --- | ||
10 | tests/qemu-iotests/iotests.py | 5 ++--- | ||
11 | 1 file changed, 2 insertions(+), 3 deletions(-) | ||
12 | |||
13 | diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py | ||
14 | index XXXXXXX..XXXXXXX 100644 | ||
15 | --- a/tests/qemu-iotests/iotests.py | ||
16 | +++ b/tests/qemu-iotests/iotests.py | ||
17 | @@ -XXX,XX +XXX,XX @@ class FilePath: | ||
18 | |||
19 | """ | ||
20 | def __init__(self, *names, base_dir=test_dir): | ||
21 | - self.paths = [] | ||
22 | - for name in names: | ||
23 | - self.paths.append(os.path.join(base_dir, file_pattern(name))) | ||
24 | + self.paths = [os.path.join(base_dir, file_pattern(name)) | ||
25 | + for name in names] | ||
26 | |||
27 | def __enter__(self): | ||
28 | if len(self.paths) == 1: | ||
29 | -- | ||
30 | 2.26.2 | ||
31 | |||
32 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | From: Lukas Straub <lukasstraub2@web.de> | ||
2 | 1 | ||
3 | If we remove the child with the highest index from the quorum, | ||
4 | decrement s->next_child_index. This way we get stable children | ||
5 | names as long as we only remove the last child. | ||
6 | |||
7 | Signed-off-by: Lukas Straub <lukasstraub2@web.de> | ||
8 | Fixes: https://bugs.launchpad.net/bugs/1881231 | ||
9 | Reviewed-by: Zhang Chen <chen.zhang@intel.com> | ||
10 | Reviewed-by: Alberto Garcia <berto@igalia.com> | ||
11 | Message-Id: <5d5f930424c1c770754041aa8ad6421dc4e2b58e.1596536719.git.lukasstraub2@web.de> | ||
12 | Signed-off-by: Max Reitz <mreitz@redhat.com> | ||
13 | --- | ||
14 | block/quorum.c | 20 ++++++++++++++------ | ||
15 | 1 file changed, 14 insertions(+), 6 deletions(-) | ||
16 | |||
17 | diff --git a/block/quorum.c b/block/quorum.c | ||
18 | index XXXXXXX..XXXXXXX 100644 | ||
19 | --- a/block/quorum.c | ||
20 | +++ b/block/quorum.c | ||
21 | @@ -XXX,XX +XXX,XX @@ | ||
22 | |||
23 | #define HASH_LENGTH 32 | ||
24 | |||
25 | +#define INDEXSTR_LEN 32 | ||
26 | + | ||
27 | #define QUORUM_OPT_VOTE_THRESHOLD "vote-threshold" | ||
28 | #define QUORUM_OPT_BLKVERIFY "blkverify" | ||
29 | #define QUORUM_OPT_REWRITE "rewrite-corrupted" | ||
30 | @@ -XXX,XX +XXX,XX @@ static int quorum_open(BlockDriverState *bs, QDict *options, int flags, | ||
31 | opened = g_new0(bool, s->num_children); | ||
32 | |||
33 | for (i = 0; i < s->num_children; i++) { | ||
34 | - char indexstr[32]; | ||
35 | - ret = snprintf(indexstr, 32, "children.%d", i); | ||
36 | - assert(ret < 32); | ||
37 | + char indexstr[INDEXSTR_LEN]; | ||
38 | + ret = snprintf(indexstr, INDEXSTR_LEN, "children.%d", i); | ||
39 | + assert(ret < INDEXSTR_LEN); | ||
40 | |||
41 | s->children[i] = bdrv_open_child(NULL, options, indexstr, bs, | ||
42 | &child_of_bds, BDRV_CHILD_DATA, false, | ||
43 | @@ -XXX,XX +XXX,XX @@ static void quorum_add_child(BlockDriverState *bs, BlockDriverState *child_bs, | ||
44 | { | ||
45 | BDRVQuorumState *s = bs->opaque; | ||
46 | BdrvChild *child; | ||
47 | - char indexstr[32]; | ||
48 | + char indexstr[INDEXSTR_LEN]; | ||
49 | int ret; | ||
50 | |||
51 | if (s->is_blkverify) { | ||
52 | @@ -XXX,XX +XXX,XX @@ static void quorum_add_child(BlockDriverState *bs, BlockDriverState *child_bs, | ||
53 | return; | ||
54 | } | ||
55 | |||
56 | - ret = snprintf(indexstr, 32, "children.%u", s->next_child_index); | ||
57 | - if (ret < 0 || ret >= 32) { | ||
58 | + ret = snprintf(indexstr, INDEXSTR_LEN, "children.%u", s->next_child_index); | ||
59 | + if (ret < 0 || ret >= INDEXSTR_LEN) { | ||
60 | error_setg(errp, "cannot generate child name"); | ||
61 | return; | ||
62 | } | ||
63 | @@ -XXX,XX +XXX,XX @@ static void quorum_del_child(BlockDriverState *bs, BdrvChild *child, | ||
64 | Error **errp) | ||
65 | { | ||
66 | BDRVQuorumState *s = bs->opaque; | ||
67 | + char indexstr[INDEXSTR_LEN]; | ||
68 | int i; | ||
69 | |||
70 | for (i = 0; i < s->num_children; i++) { | ||
71 | @@ -XXX,XX +XXX,XX @@ static void quorum_del_child(BlockDriverState *bs, BdrvChild *child, | ||
72 | /* We know now that num_children > threshold, so blkverify must be false */ | ||
73 | assert(!s->is_blkverify); | ||
74 | |||
75 | + snprintf(indexstr, INDEXSTR_LEN, "children.%u", s->next_child_index - 1); | ||
76 | + if (!strncmp(child->name, indexstr, INDEXSTR_LEN)) { | ||
77 | + s->next_child_index--; | ||
78 | + } | ||
79 | + | ||
80 | bdrv_drained_begin(bs); | ||
81 | |||
82 | /* We can safely remove this child now */ | ||
83 | -- | ||
84 | 2.26.2 | ||
85 | |||
86 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | From: Peter Lieven <pl@kamp.de> | ||
2 | 1 | ||
3 | in case of large continous areas that share the same allocation status | ||
4 | it happens that the value of s->sector_next_status is unaligned to the | ||
5 | cluster size or even request alignment of the source. Avoid this by | ||
6 | stripping down the s->sector_next_status position to cluster boundaries. | ||
7 | |||
8 | Signed-off-by: Peter Lieven <pl@kamp.de> | ||
9 | Message-Id: <20200901125129.6398-1-pl@kamp.de> | ||
10 | [mreitz: Disable vhdx for 251] | ||
11 | Signed-off-by: Max Reitz <mreitz@redhat.com> | ||
12 | --- | ||
13 | qemu-img.c | 22 ++++++++++++++++++++++ | ||
14 | tests/qemu-iotests/251 | 7 +++++-- | ||
15 | 2 files changed, 27 insertions(+), 2 deletions(-) | ||
16 | |||
17 | diff --git a/qemu-img.c b/qemu-img.c | ||
18 | index XXXXXXX..XXXXXXX 100644 | ||
19 | --- a/qemu-img.c | ||
20 | +++ b/qemu-img.c | ||
21 | @@ -XXX,XX +XXX,XX @@ enum ImgConvertBlockStatus { | ||
22 | typedef struct ImgConvertState { | ||
23 | BlockBackend **src; | ||
24 | int64_t *src_sectors; | ||
25 | + int *src_alignment; | ||
26 | int src_num; | ||
27 | int64_t total_sectors; | ||
28 | int64_t allocated_sectors; | ||
29 | @@ -XXX,XX +XXX,XX @@ static int convert_iteration_sectors(ImgConvertState *s, int64_t sector_num) | ||
30 | if (s->sector_next_status <= sector_num) { | ||
31 | uint64_t offset = (sector_num - src_cur_offset) * BDRV_SECTOR_SIZE; | ||
32 | int64_t count; | ||
33 | + int tail; | ||
34 | BlockDriverState *src_bs = blk_bs(s->src[src_cur]); | ||
35 | BlockDriverState *base; | ||
36 | |||
37 | @@ -XXX,XX +XXX,XX @@ static int convert_iteration_sectors(ImgConvertState *s, int64_t sector_num) | ||
38 | |||
39 | n = DIV_ROUND_UP(count, BDRV_SECTOR_SIZE); | ||
40 | |||
41 | + /* | ||
42 | + * Avoid that s->sector_next_status becomes unaligned to the source | ||
43 | + * request alignment and/or cluster size to avoid unnecessary read | ||
44 | + * cycles. | ||
45 | + */ | ||
46 | + tail = (sector_num - src_cur_offset + n) % s->src_alignment[src_cur]; | ||
47 | + if (n > tail) { | ||
48 | + n -= tail; | ||
49 | + } | ||
50 | + | ||
51 | if (ret & BDRV_BLOCK_ZERO) { | ||
52 | s->status = post_backing_zero ? BLK_BACKING_FILE : BLK_ZERO; | ||
53 | } else if (ret & BDRV_BLOCK_DATA) { | ||
54 | @@ -XXX,XX +XXX,XX @@ static int img_convert(int argc, char **argv) | ||
55 | |||
56 | s.src = g_new0(BlockBackend *, s.src_num); | ||
57 | s.src_sectors = g_new(int64_t, s.src_num); | ||
58 | + s.src_alignment = g_new(int, s.src_num); | ||
59 | |||
60 | for (bs_i = 0; bs_i < s.src_num; bs_i++) { | ||
61 | + BlockDriverState *src_bs; | ||
62 | s.src[bs_i] = img_open(image_opts, argv[optind + bs_i], | ||
63 | fmt, src_flags, src_writethrough, s.quiet, | ||
64 | force_share); | ||
65 | @@ -XXX,XX +XXX,XX @@ static int img_convert(int argc, char **argv) | ||
66 | ret = -1; | ||
67 | goto out; | ||
68 | } | ||
69 | + src_bs = blk_bs(s.src[bs_i]); | ||
70 | + s.src_alignment[bs_i] = DIV_ROUND_UP(src_bs->bl.request_alignment, | ||
71 | + BDRV_SECTOR_SIZE); | ||
72 | + if (!bdrv_get_info(src_bs, &bdi)) { | ||
73 | + s.src_alignment[bs_i] = MAX(s.src_alignment[bs_i], | ||
74 | + bdi.cluster_size / BDRV_SECTOR_SIZE); | ||
75 | + } | ||
76 | s.total_sectors += s.src_sectors[bs_i]; | ||
77 | } | ||
78 | |||
79 | @@ -XXX,XX +XXX,XX @@ out: | ||
80 | g_free(s.src); | ||
81 | } | ||
82 | g_free(s.src_sectors); | ||
83 | + g_free(s.src_alignment); | ||
84 | fail_getopt: | ||
85 | g_free(options); | ||
86 | |||
87 | diff --git a/tests/qemu-iotests/251 b/tests/qemu-iotests/251 | ||
88 | index XXXXXXX..XXXXXXX 100755 | ||
89 | --- a/tests/qemu-iotests/251 | ||
90 | +++ b/tests/qemu-iotests/251 | ||
91 | @@ -XXX,XX +XXX,XX @@ if [ "$IMGOPTSSYNTAX" = "true" ]; then | ||
92 | # We use json:{} filenames here, so we cannot work with additional options. | ||
93 | _unsupported_fmt $IMGFMT | ||
94 | else | ||
95 | - # With VDI, the output is ordered differently. Just disable it. | ||
96 | - _unsupported_fmt vdi | ||
97 | + # - With VDI, the output is ordered differently. Just disable it. | ||
98 | + # - VHDX has large clusters; because qemu-img convert tries to | ||
99 | + # align the requests to the cluster size, the output is ordered | ||
100 | + # differently, so disable it, too. | ||
101 | + _unsupported_fmt vdi vhdx | ||
102 | fi | ||
103 | |||
104 | |||
105 | -- | ||
106 | 2.26.2 | ||
107 | |||
108 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | From: Alberto Garcia <berto@igalia.com> | ||
2 | 1 | ||
3 | This patch replaces instances of sizeof(uint64_t) in the qcow2 driver | ||
4 | with macros that indicate what those sizes are actually referring to. | ||
5 | |||
6 | Signed-off-by: Alberto Garcia <berto@igalia.com> | ||
7 | Message-Id: <20200828110828.13833-1-berto@igalia.com> | ||
8 | Signed-off-by: Max Reitz <mreitz@redhat.com> | ||
9 | --- | ||
10 | block/qcow2.h | 6 +++ | ||
11 | block/qcow2-bitmap.c | 11 ++++-- | ||
12 | block/qcow2-cluster.c | 24 ++++++------ | ||
13 | block/qcow2-refcount.c | 89 ++++++++++++++++++++++-------------------- | ||
14 | block/qcow2-snapshot.c | 20 +++++----- | ||
15 | block/qcow2.c | 27 ++++++------- | ||
16 | 6 files changed, 94 insertions(+), 83 deletions(-) | ||
17 | |||
18 | diff --git a/block/qcow2.h b/block/qcow2.h | ||
19 | index XXXXXXX..XXXXXXX 100644 | ||
20 | --- a/block/qcow2.h | ||
21 | +++ b/block/qcow2.h | ||
22 | @@ -XXX,XX +XXX,XX @@ | ||
23 | #define L2E_SIZE_NORMAL (sizeof(uint64_t)) | ||
24 | #define L2E_SIZE_EXTENDED (sizeof(uint64_t) * 2) | ||
25 | |||
26 | +/* Size of L1 table entries */ | ||
27 | +#define L1E_SIZE (sizeof(uint64_t)) | ||
28 | + | ||
29 | +/* Size of reftable entries */ | ||
30 | +#define REFTABLE_ENTRY_SIZE (sizeof(uint64_t)) | ||
31 | + | ||
32 | #define MIN_CLUSTER_BITS 9 | ||
33 | #define MAX_CLUSTER_BITS 21 | ||
34 | |||
35 | diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c | ||
36 | index XXXXXXX..XXXXXXX 100644 | ||
37 | --- a/block/qcow2-bitmap.c | ||
38 | +++ b/block/qcow2-bitmap.c | ||
39 | @@ -XXX,XX +XXX,XX @@ | ||
40 | #define BME_MIN_GRANULARITY_BITS 9 | ||
41 | #define BME_MAX_NAME_SIZE 1023 | ||
42 | |||
43 | +/* Size of bitmap table entries */ | ||
44 | +#define BME_TABLE_ENTRY_SIZE (sizeof(uint64_t)) | ||
45 | + | ||
46 | QEMU_BUILD_BUG_ON(BME_MAX_NAME_SIZE != BDRV_BITMAP_MAX_NAME_SIZE); | ||
47 | |||
48 | #if BME_MAX_TABLE_SIZE * 8ULL > INT_MAX | ||
49 | @@ -XXX,XX +XXX,XX @@ static int bitmap_table_load(BlockDriverState *bs, Qcow2BitmapTable *tb, | ||
50 | |||
51 | assert(tb->size <= BME_MAX_TABLE_SIZE); | ||
52 | ret = bdrv_pread(bs->file, tb->offset, | ||
53 | - table, tb->size * sizeof(uint64_t)); | ||
54 | + table, tb->size * BME_TABLE_ENTRY_SIZE); | ||
55 | if (ret < 0) { | ||
56 | goto fail; | ||
57 | } | ||
58 | @@ -XXX,XX +XXX,XX @@ static int free_bitmap_clusters(BlockDriverState *bs, Qcow2BitmapTable *tb) | ||
59 | } | ||
60 | |||
61 | clear_bitmap_table(bs, bitmap_table, tb->size); | ||
62 | - qcow2_free_clusters(bs, tb->offset, tb->size * sizeof(uint64_t), | ||
63 | + qcow2_free_clusters(bs, tb->offset, tb->size * BME_TABLE_ENTRY_SIZE, | ||
64 | QCOW2_DISCARD_OTHER); | ||
65 | g_free(bitmap_table); | ||
66 | |||
67 | @@ -XXX,XX +XXX,XX @@ int qcow2_check_bitmaps_refcounts(BlockDriverState *bs, BdrvCheckResult *res, | ||
68 | ret = qcow2_inc_refcounts_imrt(bs, res, | ||
69 | refcount_table, refcount_table_size, | ||
70 | bm->table.offset, | ||
71 | - bm->table.size * sizeof(uint64_t)); | ||
72 | + bm->table.size * BME_TABLE_ENTRY_SIZE); | ||
73 | if (ret < 0) { | ||
74 | goto out; | ||
75 | } | ||
76 | @@ -XXX,XX +XXX,XX @@ uint64_t qcow2_get_persistent_dirty_bitmap_size(BlockDriverState *in_bs, | ||
77 | /* Assume the entire bitmap is allocated */ | ||
78 | bitmaps_size += bmclusters * cluster_size; | ||
79 | /* Also reserve space for the bitmap table entries */ | ||
80 | - bitmaps_size += ROUND_UP(bmclusters * sizeof(uint64_t), | ||
81 | + bitmaps_size += ROUND_UP(bmclusters * BME_TABLE_ENTRY_SIZE, | ||
82 | cluster_size); | ||
83 | /* And space for contribution to bitmap directory size */ | ||
84 | bitmap_dir_size += calc_dir_entry_size(strlen(name), 0); | ||
85 | diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c | ||
86 | index XXXXXXX..XXXXXXX 100644 | ||
87 | --- a/block/qcow2-cluster.c | ||
88 | +++ b/block/qcow2-cluster.c | ||
89 | @@ -XXX,XX +XXX,XX @@ int qcow2_shrink_l1_table(BlockDriverState *bs, uint64_t exact_size) | ||
90 | |||
91 | BLKDBG_EVENT(bs->file, BLKDBG_L1_SHRINK_WRITE_TABLE); | ||
92 | ret = bdrv_pwrite_zeroes(bs->file, s->l1_table_offset + | ||
93 | - new_l1_size * sizeof(uint64_t), | ||
94 | - (s->l1_size - new_l1_size) * sizeof(uint64_t), 0); | ||
95 | + new_l1_size * L1E_SIZE, | ||
96 | + (s->l1_size - new_l1_size) * L1E_SIZE, 0); | ||
97 | if (ret < 0) { | ||
98 | goto fail; | ||
99 | } | ||
100 | @@ -XXX,XX +XXX,XX @@ fail: | ||
101 | * l1_table in memory to avoid possible image corruption. | ||
102 | */ | ||
103 | memset(s->l1_table + new_l1_size, 0, | ||
104 | - (s->l1_size - new_l1_size) * sizeof(uint64_t)); | ||
105 | + (s->l1_size - new_l1_size) * L1E_SIZE); | ||
106 | return ret; | ||
107 | } | ||
108 | |||
109 | @@ -XXX,XX +XXX,XX @@ int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size, | ||
110 | /* Do a sanity check on min_size before trying to calculate new_l1_size | ||
111 | * (this prevents overflows during the while loop for the calculation of | ||
112 | * new_l1_size) */ | ||
113 | - if (min_size > INT_MAX / sizeof(uint64_t)) { | ||
114 | + if (min_size > INT_MAX / L1E_SIZE) { | ||
115 | return -EFBIG; | ||
116 | } | ||
117 | |||
118 | @@ -XXX,XX +XXX,XX @@ int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size, | ||
119 | } | ||
120 | |||
121 | QEMU_BUILD_BUG_ON(QCOW_MAX_L1_SIZE > INT_MAX); | ||
122 | - if (new_l1_size > QCOW_MAX_L1_SIZE / sizeof(uint64_t)) { | ||
123 | + if (new_l1_size > QCOW_MAX_L1_SIZE / L1E_SIZE) { | ||
124 | return -EFBIG; | ||
125 | } | ||
126 | |||
127 | @@ -XXX,XX +XXX,XX @@ int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size, | ||
128 | s->l1_size, new_l1_size); | ||
129 | #endif | ||
130 | |||
131 | - new_l1_size2 = sizeof(uint64_t) * new_l1_size; | ||
132 | + new_l1_size2 = L1E_SIZE * new_l1_size; | ||
133 | new_l1_table = qemu_try_blockalign(bs->file->bs, new_l1_size2); | ||
134 | if (new_l1_table == NULL) { | ||
135 | return -ENOMEM; | ||
136 | @@ -XXX,XX +XXX,XX @@ int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size, | ||
137 | memset(new_l1_table, 0, new_l1_size2); | ||
138 | |||
139 | if (s->l1_size) { | ||
140 | - memcpy(new_l1_table, s->l1_table, s->l1_size * sizeof(uint64_t)); | ||
141 | + memcpy(new_l1_table, s->l1_table, s->l1_size * L1E_SIZE); | ||
142 | } | ||
143 | |||
144 | /* write new table (align to cluster) */ | ||
145 | @@ -XXX,XX +XXX,XX @@ int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size, | ||
146 | s->l1_table = new_l1_table; | ||
147 | old_l1_size = s->l1_size; | ||
148 | s->l1_size = new_l1_size; | ||
149 | - qcow2_free_clusters(bs, old_l1_table_offset, old_l1_size * sizeof(uint64_t), | ||
150 | + qcow2_free_clusters(bs, old_l1_table_offset, old_l1_size * L1E_SIZE, | ||
151 | QCOW2_DISCARD_OTHER); | ||
152 | return 0; | ||
153 | fail: | ||
154 | @@ -XXX,XX +XXX,XX @@ int qcow2_write_l1_entry(BlockDriverState *bs, int l1_index) | ||
155 | BDRVQcow2State *s = bs->opaque; | ||
156 | int l1_start_index; | ||
157 | int i, ret; | ||
158 | - int bufsize = MAX(sizeof(uint64_t), | ||
159 | + int bufsize = MAX(L1E_SIZE, | ||
160 | MIN(bs->file->bs->bl.request_alignment, s->cluster_size)); | ||
161 | - int nentries = bufsize / sizeof(uint64_t); | ||
162 | + int nentries = bufsize / L1E_SIZE; | ||
163 | g_autofree uint64_t *buf = g_try_new0(uint64_t, nentries); | ||
164 | |||
165 | if (buf == NULL) { | ||
166 | @@ -XXX,XX +XXX,XX @@ int qcow2_expand_zero_clusters(BlockDriverState *bs, | ||
167 | Error *local_err = NULL; | ||
168 | |||
169 | ret = qcow2_validate_table(bs, s->snapshots[i].l1_table_offset, | ||
170 | - s->snapshots[i].l1_size, sizeof(uint64_t), | ||
171 | + s->snapshots[i].l1_size, L1E_SIZE, | ||
172 | QCOW_MAX_L1_SIZE, "Snapshot L1 table", | ||
173 | &local_err); | ||
174 | if (ret < 0) { | ||
175 | @@ -XXX,XX +XXX,XX @@ int qcow2_expand_zero_clusters(BlockDriverState *bs, | ||
176 | goto fail; | ||
177 | } | ||
178 | |||
179 | - l1_size2 = s->snapshots[i].l1_size * sizeof(uint64_t); | ||
180 | + l1_size2 = s->snapshots[i].l1_size * L1E_SIZE; | ||
181 | new_l1_table = g_try_realloc(l1_table, l1_size2); | ||
182 | |||
183 | if (!new_l1_table) { | ||
184 | diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c | ||
185 | index XXXXXXX..XXXXXXX 100644 | ||
186 | --- a/block/qcow2-refcount.c | ||
187 | +++ b/block/qcow2-refcount.c | ||
188 | @@ -XXX,XX +XXX,XX @@ int qcow2_refcount_init(BlockDriverState *bs) | ||
189 | s->get_refcount = get_refcount_funcs[s->refcount_order]; | ||
190 | s->set_refcount = set_refcount_funcs[s->refcount_order]; | ||
191 | |||
192 | - assert(s->refcount_table_size <= INT_MAX / sizeof(uint64_t)); | ||
193 | - refcount_table_size2 = s->refcount_table_size * sizeof(uint64_t); | ||
194 | + assert(s->refcount_table_size <= INT_MAX / REFTABLE_ENTRY_SIZE); | ||
195 | + refcount_table_size2 = s->refcount_table_size * REFTABLE_ENTRY_SIZE; | ||
196 | s->refcount_table = g_try_malloc(refcount_table_size2); | ||
197 | |||
198 | if (s->refcount_table_size > 0) { | ||
199 | @@ -XXX,XX +XXX,XX @@ static int alloc_refcount_block(BlockDriverState *bs, | ||
200 | if (refcount_table_index < s->refcount_table_size) { | ||
201 | uint64_t data64 = cpu_to_be64(new_block); | ||
202 | BLKDBG_EVENT(bs->file, BLKDBG_REFBLOCK_ALLOC_HOOKUP); | ||
203 | - ret = bdrv_pwrite_sync(bs->file, | ||
204 | - s->refcount_table_offset + refcount_table_index * sizeof(uint64_t), | ||
205 | + ret = bdrv_pwrite_sync(bs->file, s->refcount_table_offset + | ||
206 | + refcount_table_index * REFTABLE_ENTRY_SIZE, | ||
207 | &data64, sizeof(data64)); | ||
208 | if (ret < 0) { | ||
209 | goto fail; | ||
210 | @@ -XXX,XX +XXX,XX @@ int64_t qcow2_refcount_area(BlockDriverState *bs, uint64_t start_offset, | ||
211 | DIV_ROUND_UP(total_refblock_count, 2); | ||
212 | } | ||
213 | /* The qcow2 file can only store the reftable size in number of clusters */ | ||
214 | - table_size = ROUND_UP(table_size, s->cluster_size / sizeof(uint64_t)); | ||
215 | - table_clusters = (table_size * sizeof(uint64_t)) / s->cluster_size; | ||
216 | + table_size = ROUND_UP(table_size, s->cluster_size / REFTABLE_ENTRY_SIZE); | ||
217 | + table_clusters = (table_size * REFTABLE_ENTRY_SIZE) / s->cluster_size; | ||
218 | |||
219 | if (table_size > QCOW_MAX_REFTABLE_SIZE) { | ||
220 | return -EFBIG; | ||
221 | @@ -XXX,XX +XXX,XX @@ int64_t qcow2_refcount_area(BlockDriverState *bs, uint64_t start_offset, | ||
222 | if (table_size > s->max_refcount_table_index) { | ||
223 | /* We're actually growing the reftable */ | ||
224 | memcpy(new_table, s->refcount_table, | ||
225 | - (s->max_refcount_table_index + 1) * sizeof(uint64_t)); | ||
226 | + (s->max_refcount_table_index + 1) * REFTABLE_ENTRY_SIZE); | ||
227 | } else { | ||
228 | /* Improbable case: We're shrinking the reftable. However, the caller | ||
229 | * has assured us that there is only empty space beyond @start_offset, | ||
230 | * so we can simply drop all of the refblocks that won't fit into the | ||
231 | * new reftable. */ | ||
232 | - memcpy(new_table, s->refcount_table, table_size * sizeof(uint64_t)); | ||
233 | + memcpy(new_table, s->refcount_table, table_size * REFTABLE_ENTRY_SIZE); | ||
234 | } | ||
235 | |||
236 | if (new_refblock_offset) { | ||
237 | @@ -XXX,XX +XXX,XX @@ int64_t qcow2_refcount_area(BlockDriverState *bs, uint64_t start_offset, | ||
238 | |||
239 | BLKDBG_EVENT(bs->file, BLKDBG_REFBLOCK_ALLOC_WRITE_TABLE); | ||
240 | ret = bdrv_pwrite_sync(bs->file, table_offset, new_table, | ||
241 | - table_size * sizeof(uint64_t)); | ||
242 | + table_size * REFTABLE_ENTRY_SIZE); | ||
243 | if (ret < 0) { | ||
244 | goto fail; | ||
245 | } | ||
246 | @@ -XXX,XX +XXX,XX @@ int64_t qcow2_refcount_area(BlockDriverState *bs, uint64_t start_offset, | ||
247 | update_max_refcount_table_index(s); | ||
248 | |||
249 | /* Free old table. */ | ||
250 | - qcow2_free_clusters(bs, old_table_offset, old_table_size * sizeof(uint64_t), | ||
251 | + qcow2_free_clusters(bs, old_table_offset, | ||
252 | + old_table_size * REFTABLE_ENTRY_SIZE, | ||
253 | QCOW2_DISCARD_OTHER); | ||
254 | |||
255 | return end_offset; | ||
256 | @@ -XXX,XX +XXX,XX @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs, | ||
257 | |||
258 | l2_slice = NULL; | ||
259 | l1_table = NULL; | ||
260 | - l1_size2 = l1_size * sizeof(uint64_t); | ||
261 | + l1_size2 = l1_size * L1E_SIZE; | ||
262 | slice_size2 = s->l2_slice_size * l2_entry_size(s); | ||
263 | n_slices = s->cluster_size / slice_size2; | ||
264 | |||
265 | @@ -XXX,XX +XXX,XX @@ static int check_refcounts_l1(BlockDriverState *bs, | ||
266 | uint64_t *l1_table = NULL, l2_offset, l1_size2; | ||
267 | int i, ret; | ||
268 | |||
269 | - l1_size2 = l1_size * sizeof(uint64_t); | ||
270 | + l1_size2 = l1_size * L1E_SIZE; | ||
271 | |||
272 | /* Mark L1 table as used */ | ||
273 | ret = qcow2_inc_refcounts_imrt(bs, res, refcount_table, refcount_table_size, | ||
274 | @@ -XXX,XX +XXX,XX @@ static int calculate_refcounts(BlockDriverState *bs, BdrvCheckResult *res, | ||
275 | res->corruptions++; | ||
276 | continue; | ||
277 | } | ||
278 | - if (sn->l1_size > QCOW_MAX_L1_SIZE / sizeof(uint64_t)) { | ||
279 | + if (sn->l1_size > QCOW_MAX_L1_SIZE / L1E_SIZE) { | ||
280 | fprintf(stderr, "ERROR snapshot %s (%s) l1_size=%#" PRIx32 ": " | ||
281 | "L1 table is too large; snapshot table entry corrupted\n", | ||
282 | sn->id_str, sn->name, sn->l1_size); | ||
283 | @@ -XXX,XX +XXX,XX @@ static int calculate_refcounts(BlockDriverState *bs, BdrvCheckResult *res, | ||
284 | /* refcount data */ | ||
285 | ret = qcow2_inc_refcounts_imrt(bs, res, refcount_table, nb_clusters, | ||
286 | s->refcount_table_offset, | ||
287 | - s->refcount_table_size * sizeof(uint64_t)); | ||
288 | + s->refcount_table_size * | ||
289 | + REFTABLE_ENTRY_SIZE); | ||
290 | if (ret < 0) { | ||
291 | return ret; | ||
292 | } | ||
293 | @@ -XXX,XX +XXX,XX @@ write_refblocks: | ||
294 | uint32_t old_reftable_size = reftable_size; | ||
295 | uint64_t *new_on_disk_reftable; | ||
296 | |||
297 | - reftable_size = ROUND_UP((refblock_index + 1) * sizeof(uint64_t), | ||
298 | - s->cluster_size) / sizeof(uint64_t); | ||
299 | + reftable_size = ROUND_UP((refblock_index + 1) * REFTABLE_ENTRY_SIZE, | ||
300 | + s->cluster_size) / REFTABLE_ENTRY_SIZE; | ||
301 | new_on_disk_reftable = g_try_realloc(on_disk_reftable, | ||
302 | reftable_size * | ||
303 | - sizeof(uint64_t)); | ||
304 | + REFTABLE_ENTRY_SIZE); | ||
305 | if (!new_on_disk_reftable) { | ||
306 | res->check_errors++; | ||
307 | ret = -ENOMEM; | ||
308 | @@ -XXX,XX +XXX,XX @@ write_refblocks: | ||
309 | on_disk_reftable = new_on_disk_reftable; | ||
310 | |||
311 | memset(on_disk_reftable + old_reftable_size, 0, | ||
312 | - (reftable_size - old_reftable_size) * sizeof(uint64_t)); | ||
313 | + (reftable_size - old_reftable_size) * REFTABLE_ENTRY_SIZE); | ||
314 | |||
315 | /* The offset we have for the reftable is now no longer valid; | ||
316 | * this will leak that range, but we can easily fix that by running | ||
317 | @@ -XXX,XX +XXX,XX @@ write_refblocks: | ||
318 | reftable_offset < 0) | ||
319 | { | ||
320 | uint64_t reftable_clusters = size_to_clusters(s, reftable_size * | ||
321 | - sizeof(uint64_t)); | ||
322 | + REFTABLE_ENTRY_SIZE); | ||
323 | reftable_offset = alloc_clusters_imrt(bs, reftable_clusters, | ||
324 | refcount_table, nb_clusters, | ||
325 | &first_free_cluster); | ||
326 | @@ -XXX,XX +XXX,XX @@ write_refblocks: | ||
327 | uint64_t post_refblock_start, reftable_clusters; | ||
328 | |||
329 | post_refblock_start = ROUND_UP(*nb_clusters, s->refcount_block_size); | ||
330 | - reftable_clusters = size_to_clusters(s, | ||
331 | - reftable_size * sizeof(uint64_t)); | ||
332 | + reftable_clusters = | ||
333 | + size_to_clusters(s, reftable_size * REFTABLE_ENTRY_SIZE); | ||
334 | /* Not pretty but simple */ | ||
335 | if (first_free_cluster < post_refblock_start) { | ||
336 | first_free_cluster = post_refblock_start; | ||
337 | @@ -XXX,XX +XXX,XX @@ write_refblocks: | ||
338 | } | ||
339 | |||
340 | ret = qcow2_pre_write_overlap_check(bs, 0, reftable_offset, | ||
341 | - reftable_size * sizeof(uint64_t), | ||
342 | + reftable_size * REFTABLE_ENTRY_SIZE, | ||
343 | false); | ||
344 | if (ret < 0) { | ||
345 | fprintf(stderr, "ERROR writing reftable: %s\n", strerror(-ret)); | ||
346 | goto fail; | ||
347 | } | ||
348 | |||
349 | - assert(reftable_size < INT_MAX / sizeof(uint64_t)); | ||
350 | + assert(reftable_size < INT_MAX / REFTABLE_ENTRY_SIZE); | ||
351 | ret = bdrv_pwrite(bs->file, reftable_offset, on_disk_reftable, | ||
352 | - reftable_size * sizeof(uint64_t)); | ||
353 | + reftable_size * REFTABLE_ENTRY_SIZE); | ||
354 | if (ret < 0) { | ||
355 | fprintf(stderr, "ERROR writing reftable: %s\n", strerror(-ret)); | ||
356 | goto fail; | ||
357 | @@ -XXX,XX +XXX,XX @@ write_refblocks: | ||
358 | /* Enter new reftable into the image header */ | ||
359 | reftable_offset_and_clusters.reftable_offset = cpu_to_be64(reftable_offset); | ||
360 | reftable_offset_and_clusters.reftable_clusters = | ||
361 | - cpu_to_be32(size_to_clusters(s, reftable_size * sizeof(uint64_t))); | ||
362 | + cpu_to_be32(size_to_clusters(s, reftable_size * REFTABLE_ENTRY_SIZE)); | ||
363 | ret = bdrv_pwrite_sync(bs->file, | ||
364 | offsetof(QCowHeader, refcount_table_offset), | ||
365 | &reftable_offset_and_clusters, | ||
366 | @@ -XXX,XX +XXX,XX @@ int qcow2_check_metadata_overlap(BlockDriverState *bs, int ign, int64_t offset, | ||
367 | offset = start_of_cluster(s, offset); | ||
368 | |||
369 | if ((chk & QCOW2_OL_ACTIVE_L1) && s->l1_size) { | ||
370 | - if (overlaps_with(s->l1_table_offset, s->l1_size * sizeof(uint64_t))) { | ||
371 | + if (overlaps_with(s->l1_table_offset, s->l1_size * L1E_SIZE)) { | ||
372 | return QCOW2_OL_ACTIVE_L1; | ||
373 | } | ||
374 | } | ||
375 | |||
376 | if ((chk & QCOW2_OL_REFCOUNT_TABLE) && s->refcount_table_size) { | ||
377 | if (overlaps_with(s->refcount_table_offset, | ||
378 | - s->refcount_table_size * sizeof(uint64_t))) { | ||
379 | + s->refcount_table_size * REFTABLE_ENTRY_SIZE)) { | ||
380 | return QCOW2_OL_REFCOUNT_TABLE; | ||
381 | } | ||
382 | } | ||
383 | @@ -XXX,XX +XXX,XX @@ int qcow2_check_metadata_overlap(BlockDriverState *bs, int ign, int64_t offset, | ||
384 | for (i = 0; i < s->nb_snapshots; i++) { | ||
385 | if (s->snapshots[i].l1_size && | ||
386 | overlaps_with(s->snapshots[i].l1_table_offset, | ||
387 | - s->snapshots[i].l1_size * sizeof(uint64_t))) { | ||
388 | + s->snapshots[i].l1_size * L1E_SIZE)) { | ||
389 | return QCOW2_OL_INACTIVE_L1; | ||
390 | } | ||
391 | } | ||
392 | @@ -XXX,XX +XXX,XX @@ int qcow2_check_metadata_overlap(BlockDriverState *bs, int ign, int64_t offset, | ||
393 | for (i = 0; i < s->nb_snapshots; i++) { | ||
394 | uint64_t l1_ofs = s->snapshots[i].l1_table_offset; | ||
395 | uint32_t l1_sz = s->snapshots[i].l1_size; | ||
396 | - uint64_t l1_sz2 = l1_sz * sizeof(uint64_t); | ||
397 | + uint64_t l1_sz2 = l1_sz * L1E_SIZE; | ||
398 | uint64_t *l1; | ||
399 | int ret; | ||
400 | |||
401 | - ret = qcow2_validate_table(bs, l1_ofs, l1_sz, sizeof(uint64_t), | ||
402 | + ret = qcow2_validate_table(bs, l1_ofs, l1_sz, L1E_SIZE, | ||
403 | QCOW_MAX_L1_SIZE, "", NULL); | ||
404 | if (ret < 0) { | ||
405 | return ret; | ||
406 | @@ -XXX,XX +XXX,XX @@ static int alloc_refblock(BlockDriverState *bs, uint64_t **reftable, | ||
407 | uint64_t new_reftable_size; | ||
408 | |||
409 | new_reftable_size = ROUND_UP(reftable_index + 1, | ||
410 | - s->cluster_size / sizeof(uint64_t)); | ||
411 | - if (new_reftable_size > QCOW_MAX_REFTABLE_SIZE / sizeof(uint64_t)) { | ||
412 | + s->cluster_size / REFTABLE_ENTRY_SIZE); | ||
413 | + if (new_reftable_size > QCOW_MAX_REFTABLE_SIZE / REFTABLE_ENTRY_SIZE) { | ||
414 | error_setg(errp, | ||
415 | "This operation would make the refcount table grow " | ||
416 | "beyond the maximum size supported by QEMU, aborting"); | ||
417 | @@ -XXX,XX +XXX,XX @@ static int alloc_refblock(BlockDriverState *bs, uint64_t **reftable, | ||
418 | } | ||
419 | |||
420 | new_reftable = g_try_realloc(*reftable, new_reftable_size * | ||
421 | - sizeof(uint64_t)); | ||
422 | + REFTABLE_ENTRY_SIZE); | ||
423 | if (!new_reftable) { | ||
424 | error_setg(errp, "Failed to increase reftable buffer size"); | ||
425 | return -ENOMEM; | ||
426 | } | ||
427 | |||
428 | memset(new_reftable + *reftable_size, 0, | ||
429 | - (new_reftable_size - *reftable_size) * sizeof(uint64_t)); | ||
430 | + (new_reftable_size - *reftable_size) * REFTABLE_ENTRY_SIZE); | ||
431 | |||
432 | *reftable = new_reftable; | ||
433 | *reftable_size = new_reftable_size; | ||
434 | @@ -XXX,XX +XXX,XX @@ int qcow2_change_refcount_order(BlockDriverState *bs, int refcount_order, | ||
435 | |||
436 | if (new_allocation) { | ||
437 | if (new_reftable_offset) { | ||
438 | - qcow2_free_clusters(bs, new_reftable_offset, | ||
439 | - allocated_reftable_size * sizeof(uint64_t), | ||
440 | - QCOW2_DISCARD_NEVER); | ||
441 | + qcow2_free_clusters( | ||
442 | + bs, new_reftable_offset, | ||
443 | + allocated_reftable_size * REFTABLE_ENTRY_SIZE, | ||
444 | + QCOW2_DISCARD_NEVER); | ||
445 | } | ||
446 | |||
447 | new_reftable_offset = qcow2_alloc_clusters(bs, new_reftable_size * | ||
448 | - sizeof(uint64_t)); | ||
449 | + REFTABLE_ENTRY_SIZE); | ||
450 | if (new_reftable_offset < 0) { | ||
451 | error_setg_errno(errp, -new_reftable_offset, | ||
452 | "Failed to allocate the new reftable"); | ||
453 | @@ -XXX,XX +XXX,XX @@ int qcow2_change_refcount_order(BlockDriverState *bs, int refcount_order, | ||
454 | |||
455 | /* Write the new reftable */ | ||
456 | ret = qcow2_pre_write_overlap_check(bs, 0, new_reftable_offset, | ||
457 | - new_reftable_size * sizeof(uint64_t), | ||
458 | + new_reftable_size * REFTABLE_ENTRY_SIZE, | ||
459 | false); | ||
460 | if (ret < 0) { | ||
461 | error_setg_errno(errp, -ret, "Overlap check failed"); | ||
462 | @@ -XXX,XX +XXX,XX @@ int qcow2_change_refcount_order(BlockDriverState *bs, int refcount_order, | ||
463 | } | ||
464 | |||
465 | ret = bdrv_pwrite(bs->file, new_reftable_offset, new_reftable, | ||
466 | - new_reftable_size * sizeof(uint64_t)); | ||
467 | + new_reftable_size * REFTABLE_ENTRY_SIZE); | ||
468 | |||
469 | for (i = 0; i < new_reftable_size; i++) { | ||
470 | be64_to_cpus(&new_reftable[i]); | ||
471 | @@ -XXX,XX +XXX,XX @@ done: | ||
472 | |||
473 | if (new_reftable_offset > 0) { | ||
474 | qcow2_free_clusters(bs, new_reftable_offset, | ||
475 | - new_reftable_size * sizeof(uint64_t), | ||
476 | + new_reftable_size * REFTABLE_ENTRY_SIZE, | ||
477 | QCOW2_DISCARD_OTHER); | ||
478 | } | ||
479 | } | ||
480 | @@ -XXX,XX +XXX,XX @@ int qcow2_shrink_reftable(BlockDriverState *bs) | ||
481 | { | ||
482 | BDRVQcow2State *s = bs->opaque; | ||
483 | uint64_t *reftable_tmp = | ||
484 | - g_malloc(s->refcount_table_size * sizeof(uint64_t)); | ||
485 | + g_malloc(s->refcount_table_size * REFTABLE_ENTRY_SIZE); | ||
486 | int i, ret; | ||
487 | |||
488 | for (i = 0; i < s->refcount_table_size; i++) { | ||
489 | @@ -XXX,XX +XXX,XX @@ int qcow2_shrink_reftable(BlockDriverState *bs) | ||
490 | } | ||
491 | |||
492 | ret = bdrv_pwrite_sync(bs->file, s->refcount_table_offset, reftable_tmp, | ||
493 | - s->refcount_table_size * sizeof(uint64_t)); | ||
494 | + s->refcount_table_size * REFTABLE_ENTRY_SIZE); | ||
495 | /* | ||
496 | * If the write in the reftable failed the image may contain a partially | ||
497 | * overwritten reftable. In this case it would be better to clear the | ||
498 | diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c | ||
499 | index XXXXXXX..XXXXXXX 100644 | ||
500 | --- a/block/qcow2-snapshot.c | ||
501 | +++ b/block/qcow2-snapshot.c | ||
502 | @@ -XXX,XX +XXX,XX @@ int qcow2_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info) | ||
503 | sn->extra_data_size = sizeof(QCowSnapshotExtraData); | ||
504 | |||
505 | /* Allocate the L1 table of the snapshot and copy the current one there. */ | ||
506 | - l1_table_offset = qcow2_alloc_clusters(bs, s->l1_size * sizeof(uint64_t)); | ||
507 | + l1_table_offset = qcow2_alloc_clusters(bs, s->l1_size * L1E_SIZE); | ||
508 | if (l1_table_offset < 0) { | ||
509 | ret = l1_table_offset; | ||
510 | goto fail; | ||
511 | @@ -XXX,XX +XXX,XX @@ int qcow2_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info) | ||
512 | } | ||
513 | |||
514 | ret = qcow2_pre_write_overlap_check(bs, 0, sn->l1_table_offset, | ||
515 | - s->l1_size * sizeof(uint64_t), false); | ||
516 | + s->l1_size * L1E_SIZE, false); | ||
517 | if (ret < 0) { | ||
518 | goto fail; | ||
519 | } | ||
520 | |||
521 | ret = bdrv_pwrite(bs->file, sn->l1_table_offset, l1_table, | ||
522 | - s->l1_size * sizeof(uint64_t)); | ||
523 | + s->l1_size * L1E_SIZE); | ||
524 | if (ret < 0) { | ||
525 | goto fail; | ||
526 | } | ||
527 | @@ -XXX,XX +XXX,XX @@ int qcow2_snapshot_goto(BlockDriverState *bs, const char *snapshot_id) | ||
528 | sn = &s->snapshots[snapshot_index]; | ||
529 | |||
530 | ret = qcow2_validate_table(bs, sn->l1_table_offset, sn->l1_size, | ||
531 | - sizeof(uint64_t), QCOW_MAX_L1_SIZE, | ||
532 | + L1E_SIZE, QCOW_MAX_L1_SIZE, | ||
533 | "Snapshot L1 table", &local_err); | ||
534 | if (ret < 0) { | ||
535 | error_report_err(local_err); | ||
536 | @@ -XXX,XX +XXX,XX @@ int qcow2_snapshot_goto(BlockDriverState *bs, const char *snapshot_id) | ||
537 | goto fail; | ||
538 | } | ||
539 | |||
540 | - cur_l1_bytes = s->l1_size * sizeof(uint64_t); | ||
541 | - sn_l1_bytes = sn->l1_size * sizeof(uint64_t); | ||
542 | + cur_l1_bytes = s->l1_size * L1E_SIZE; | ||
543 | + sn_l1_bytes = sn->l1_size * L1E_SIZE; | ||
544 | |||
545 | /* | ||
546 | * Copy the snapshot L1 table to the current L1 table. | ||
547 | @@ -XXX,XX +XXX,XX @@ int qcow2_snapshot_delete(BlockDriverState *bs, | ||
548 | sn = s->snapshots[snapshot_index]; | ||
549 | |||
550 | ret = qcow2_validate_table(bs, sn.l1_table_offset, sn.l1_size, | ||
551 | - sizeof(uint64_t), QCOW_MAX_L1_SIZE, | ||
552 | + L1E_SIZE, QCOW_MAX_L1_SIZE, | ||
553 | "Snapshot L1 table", errp); | ||
554 | if (ret < 0) { | ||
555 | return ret; | ||
556 | @@ -XXX,XX +XXX,XX @@ int qcow2_snapshot_delete(BlockDriverState *bs, | ||
557 | error_setg_errno(errp, -ret, "Failed to free the cluster and L1 table"); | ||
558 | return ret; | ||
559 | } | ||
560 | - qcow2_free_clusters(bs, sn.l1_table_offset, sn.l1_size * sizeof(uint64_t), | ||
561 | + qcow2_free_clusters(bs, sn.l1_table_offset, sn.l1_size * L1E_SIZE, | ||
562 | QCOW2_DISCARD_SNAPSHOT); | ||
563 | |||
564 | /* must update the copied flag on the current cluster offsets */ | ||
565 | @@ -XXX,XX +XXX,XX @@ int qcow2_snapshot_load_tmp(BlockDriverState *bs, | ||
566 | |||
567 | /* Allocate and read in the snapshot's L1 table */ | ||
568 | ret = qcow2_validate_table(bs, sn->l1_table_offset, sn->l1_size, | ||
569 | - sizeof(uint64_t), QCOW_MAX_L1_SIZE, | ||
570 | + L1E_SIZE, QCOW_MAX_L1_SIZE, | ||
571 | "Snapshot L1 table", errp); | ||
572 | if (ret < 0) { | ||
573 | return ret; | ||
574 | } | ||
575 | - new_l1_bytes = sn->l1_size * sizeof(uint64_t); | ||
576 | + new_l1_bytes = sn->l1_size * L1E_SIZE; | ||
577 | new_l1_table = qemu_try_blockalign(bs->file->bs, new_l1_bytes); | ||
578 | if (new_l1_table == NULL) { | ||
579 | return -ENOMEM; | ||
580 | diff --git a/block/qcow2.c b/block/qcow2.c | ||
581 | index XXXXXXX..XXXXXXX 100644 | ||
582 | --- a/block/qcow2.c | ||
583 | +++ b/block/qcow2.c | ||
584 | @@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options, | ||
585 | |||
586 | /* read the level 1 table */ | ||
587 | ret = qcow2_validate_table(bs, header.l1_table_offset, | ||
588 | - header.l1_size, sizeof(uint64_t), | ||
589 | + header.l1_size, L1E_SIZE, | ||
590 | QCOW_MAX_L1_SIZE, "Active L1 table", errp); | ||
591 | if (ret < 0) { | ||
592 | goto fail; | ||
593 | @@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options, | ||
594 | } | ||
595 | |||
596 | if (s->l1_size > 0) { | ||
597 | - s->l1_table = qemu_try_blockalign(bs->file->bs, | ||
598 | - s->l1_size * sizeof(uint64_t)); | ||
599 | + s->l1_table = qemu_try_blockalign(bs->file->bs, s->l1_size * L1E_SIZE); | ||
600 | if (s->l1_table == NULL) { | ||
601 | error_setg(errp, "Could not allocate L1 table"); | ||
602 | ret = -ENOMEM; | ||
603 | goto fail; | ||
604 | } | ||
605 | ret = bdrv_pread(bs->file, s->l1_table_offset, s->l1_table, | ||
606 | - s->l1_size * sizeof(uint64_t)); | ||
607 | + s->l1_size * L1E_SIZE); | ||
608 | if (ret < 0) { | ||
609 | error_setg_errno(errp, -ret, "Could not read L1 table"); | ||
610 | goto fail; | ||
611 | @@ -XXX,XX +XXX,XX @@ int64_t qcow2_refcount_metadata_size(int64_t clusters, size_t cluster_size, | ||
612 | * where no further refcount blocks or table clusters are required to | ||
613 | * reference count every cluster. | ||
614 | */ | ||
615 | - int64_t blocks_per_table_cluster = cluster_size / sizeof(uint64_t); | ||
616 | + int64_t blocks_per_table_cluster = cluster_size / REFTABLE_ENTRY_SIZE; | ||
617 | int64_t refcounts_per_block = cluster_size * 8 / (1 << refcount_order); | ||
618 | int64_t table = 0; /* number of refcount table clusters */ | ||
619 | int64_t blocks = 0; /* number of refcount block clusters */ | ||
620 | @@ -XXX,XX +XXX,XX @@ static int64_t qcow2_calc_prealloc_size(int64_t total_size, | ||
621 | |||
622 | /* total size of L1 tables */ | ||
623 | nl1e = nl2e * l2e_size / cluster_size; | ||
624 | - nl1e = ROUND_UP(nl1e, cluster_size / sizeof(uint64_t)); | ||
625 | - meta_size += nl1e * sizeof(uint64_t); | ||
626 | + nl1e = ROUND_UP(nl1e, cluster_size / L1E_SIZE); | ||
627 | + meta_size += nl1e * L1E_SIZE; | ||
628 | |||
629 | /* total size of refcount table and blocks */ | ||
630 | meta_size += qcow2_refcount_metadata_size( | ||
631 | @@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset, | ||
632 | /* write updated header.size */ | ||
633 | offset = cpu_to_be64(offset); | ||
634 | ret = bdrv_pwrite_sync(bs->file, offsetof(QCowHeader, size), | ||
635 | - &offset, sizeof(uint64_t)); | ||
636 | + &offset, sizeof(offset)); | ||
637 | if (ret < 0) { | ||
638 | error_setg_errno(errp, -ret, "Failed to update the image size"); | ||
639 | goto fail; | ||
640 | @@ -XXX,XX +XXX,XX @@ static int make_completely_empty(BlockDriverState *bs) | ||
641 | |||
642 | BLKDBG_EVENT(bs->file, BLKDBG_L1_UPDATE); | ||
643 | |||
644 | - l1_clusters = DIV_ROUND_UP(s->l1_size, s->cluster_size / sizeof(uint64_t)); | ||
645 | - l1_size2 = (uint64_t)s->l1_size * sizeof(uint64_t); | ||
646 | + l1_clusters = DIV_ROUND_UP(s->l1_size, s->cluster_size / L1E_SIZE); | ||
647 | + l1_size2 = (uint64_t)s->l1_size * L1E_SIZE; | ||
648 | |||
649 | /* After this call, neither the in-memory nor the on-disk refcount | ||
650 | * information accurately describe the actual references */ | ||
651 | @@ -XXX,XX +XXX,XX @@ static int make_completely_empty(BlockDriverState *bs) | ||
652 | |||
653 | s->l1_table_offset = 3 * s->cluster_size; | ||
654 | |||
655 | - new_reftable = g_try_new0(uint64_t, s->cluster_size / sizeof(uint64_t)); | ||
656 | + new_reftable = g_try_new0(uint64_t, s->cluster_size / REFTABLE_ENTRY_SIZE); | ||
657 | if (!new_reftable) { | ||
658 | ret = -ENOMEM; | ||
659 | goto fail_broken_refcounts; | ||
660 | } | ||
661 | |||
662 | s->refcount_table_offset = s->cluster_size; | ||
663 | - s->refcount_table_size = s->cluster_size / sizeof(uint64_t); | ||
664 | + s->refcount_table_size = s->cluster_size / REFTABLE_ENTRY_SIZE; | ||
665 | s->max_refcount_table_index = 0; | ||
666 | |||
667 | g_free(s->refcount_table); | ||
668 | @@ -XXX,XX +XXX,XX @@ static int qcow2_make_empty(BlockDriverState *bs) | ||
669 | int step = QEMU_ALIGN_DOWN(INT_MAX, s->cluster_size); | ||
670 | int l1_clusters, ret = 0; | ||
671 | |||
672 | - l1_clusters = DIV_ROUND_UP(s->l1_size, s->cluster_size / sizeof(uint64_t)); | ||
673 | + l1_clusters = DIV_ROUND_UP(s->l1_size, s->cluster_size / L1E_SIZE); | ||
674 | |||
675 | if (s->qcow_version >= 3 && !s->snapshots && !s->nb_bitmaps && | ||
676 | 3 + l1_clusters <= s->refcount_block_size && | ||
677 | @@ -XXX,XX +XXX,XX @@ static BlockMeasureInfo *qcow2_measure(QemuOpts *opts, BlockDriverState *in_bs, | ||
678 | l2e_size = extended_l2 ? L2E_SIZE_EXTENDED : L2E_SIZE_NORMAL; | ||
679 | l2_tables = DIV_ROUND_UP(virtual_size / cluster_size, | ||
680 | cluster_size / l2e_size); | ||
681 | - if (l2_tables * sizeof(uint64_t) > QCOW_MAX_L1_SIZE) { | ||
682 | + if (l2_tables * L1E_SIZE > QCOW_MAX_L1_SIZE) { | ||
683 | error_setg(&local_err, "The image size is too large " | ||
684 | "(try using a larger cluster size)"); | ||
685 | goto err; | ||
686 | -- | ||
687 | 2.26.2 | ||
688 | |||
689 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | From: Alberto Garcia <berto@igalia.com> | ||
2 | 1 | ||
3 | When a write request needs to allocate new clusters (or change the L2 | ||
4 | bitmap of existing ones) a QCowL2Meta structure is created so the L2 | ||
5 | metadata can be later updated and any copy-on-write can be performed | ||
6 | if necessary. | ||
7 | |||
8 | A write request can span a region consisting of an arbitrary | ||
9 | combination of previously unallocated and allocated clusters, and if | ||
10 | the unallocated ones can be put contiguous to the existing ones then | ||
11 | QEMU will do so in order to minimize the number of write operations. | ||
12 | |||
13 | In practice this means that a write request has not just one but a | ||
14 | number of QCowL2Meta structures. All of them are added to the | ||
15 | cluster_allocs list that is stored in BDRVQcow2State and is used to | ||
16 | detect overlapping requests. After the write request finishes all its | ||
17 | associated QCowL2Meta are removed from that list. calculate_l2_meta() | ||
18 | takes care of creating and putting those structures in the list, and | ||
19 | qcow2_handle_l2meta() takes care of removing them. | ||
20 | |||
21 | The problem is that the error path in handle_alloc() also tries to | ||
22 | remove an item in that list, a remnant from the time when this was | ||
23 | handled there (that code would not even be correct anymore because | ||
24 | it only removes one struct and not all the ones from the same write | ||
25 | request). | ||
26 | |||
27 | This can trigger a double removal of the same item from the list, | ||
28 | causing a crash. This is not easy to reproduce in practice because | ||
29 | it requires that do_alloc_cluster_offset() fails after a successful | ||
30 | previous allocation during the same write request, but it can be | ||
31 | reproduced with the included test case. | ||
32 | |||
33 | Signed-off-by: Alberto Garcia <berto@igalia.com> | ||
34 | Message-Id: <3440a1c4d53c4fe48312b478c96accb338cbef7c.1599150873.git.berto@igalia.com> | ||
35 | Signed-off-by: Max Reitz <mreitz@redhat.com> | ||
36 | --- | ||
37 | block/qcow2-cluster.c | 3 -- | ||
38 | tests/qemu-iotests/305 | 74 ++++++++++++++++++++++++++++++++++++++ | ||
39 | tests/qemu-iotests/305.out | 16 +++++++++ | ||
40 | tests/qemu-iotests/group | 1 + | ||
41 | 4 files changed, 91 insertions(+), 3 deletions(-) | ||
42 | create mode 100755 tests/qemu-iotests/305 | ||
43 | create mode 100644 tests/qemu-iotests/305.out | ||
44 | |||
45 | diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c | ||
46 | index XXXXXXX..XXXXXXX 100644 | ||
47 | --- a/block/qcow2-cluster.c | ||
48 | +++ b/block/qcow2-cluster.c | ||
49 | @@ -XXX,XX +XXX,XX @@ static int handle_alloc(BlockDriverState *bs, uint64_t guest_offset, | ||
50 | |||
51 | out: | ||
52 | qcow2_cache_put(s->l2_table_cache, (void **) &l2_slice); | ||
53 | - if (ret < 0 && *m && (*m)->nb_clusters > 0) { | ||
54 | - QLIST_REMOVE(*m, next_in_flight); | ||
55 | - } | ||
56 | return ret; | ||
57 | } | ||
58 | |||
59 | diff --git a/tests/qemu-iotests/305 b/tests/qemu-iotests/305 | ||
60 | new file mode 100755 | ||
61 | index XXXXXXX..XXXXXXX | ||
62 | --- /dev/null | ||
63 | +++ b/tests/qemu-iotests/305 | ||
64 | @@ -XXX,XX +XXX,XX @@ | ||
65 | +#!/usr/bin/env bash | ||
66 | +# | ||
67 | +# Test the handling of errors in write requests with multiple allocations | ||
68 | +# | ||
69 | +# Copyright (C) 2020 Igalia, S.L. | ||
70 | +# Author: Alberto Garcia <berto@igalia.com> | ||
71 | +# | ||
72 | +# This program is free software; you can redistribute it and/or modify | ||
73 | +# it under the terms of the GNU General Public License as published by | ||
74 | +# the Free Software Foundation; either version 2 of the License, or | ||
75 | +# (at your option) any later version. | ||
76 | +# | ||
77 | +# This program is distributed in the hope that it will be useful, | ||
78 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
79 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
80 | +# GNU General Public License for more details. | ||
81 | +# | ||
82 | +# You should have received a copy of the GNU General Public License | ||
83 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
84 | +# | ||
85 | + | ||
86 | +# creator | ||
87 | +owner=berto@igalia.com | ||
88 | + | ||
89 | +seq=`basename $0` | ||
90 | +echo "QA output created by $seq" | ||
91 | + | ||
92 | +status=1 # failure is the default! | ||
93 | + | ||
94 | +_cleanup() | ||
95 | +{ | ||
96 | + _cleanup_test_img | ||
97 | +} | ||
98 | +trap "_cleanup; exit \$status" 0 1 2 3 15 | ||
99 | + | ||
100 | +# get standard environment, filters and checks | ||
101 | +. ./common.rc | ||
102 | +. ./common.filter | ||
103 | + | ||
104 | +_supported_fmt qcow2 | ||
105 | +_supported_proto file | ||
106 | +_supported_os Linux | ||
107 | +_unsupported_imgopts cluster_size refcount_bits extended_l2 compat=0.10 data_file | ||
108 | + | ||
109 | +echo '### Create the image' | ||
110 | +_make_test_img -o refcount_bits=64,cluster_size=1k 1M | ||
111 | + | ||
112 | +# The reference counts of the clusters for the first 123k of this | ||
113 | +# write request are stored in the first refcount block. The last | ||
114 | +# cluster (guest offset 123k) is referenced in the second refcount | ||
115 | +# block. | ||
116 | +echo '### Fill the first refcount block and one data cluster from the second' | ||
117 | +$QEMU_IO -c 'write 0 124k' "$TEST_IMG" | _filter_qemu_io | ||
118 | + | ||
119 | +echo '### Discard two of the last data clusters, leave one in the middle' | ||
120 | +$QEMU_IO -c 'discard 121k 1k' "$TEST_IMG" | _filter_qemu_io | ||
121 | +$QEMU_IO -c 'discard 123k 1k' "$TEST_IMG" | _filter_qemu_io | ||
122 | + | ||
123 | +echo '### Corrupt the offset of the second refcount block' | ||
124 | +refcount_table_offset=$(peek_file_be "$TEST_IMG" 48 8) | ||
125 | +poke_file "$TEST_IMG" $(($refcount_table_offset+14)) "\x06" | ||
126 | + | ||
127 | +# This tries to allocate the two clusters discarded earlier (guest | ||
128 | +# offsets 121k and 123k). Their reference counts are in the first and | ||
129 | +# second refcount blocks respectively, but only the first one can be | ||
130 | +# allocated correctly because the second entry of the refcount table | ||
131 | +# is corrupted. | ||
132 | +echo '### Try to allocate the discarded clusters again' | ||
133 | +$QEMU_IO -c 'write 121k 3k' "$TEST_IMG" | _filter_qemu_io | ||
134 | + | ||
135 | +# success, all done | ||
136 | +echo "*** done" | ||
137 | +rm -f $seq.full | ||
138 | +status=0 | ||
139 | diff --git a/tests/qemu-iotests/305.out b/tests/qemu-iotests/305.out | ||
140 | new file mode 100644 | ||
141 | index XXXXXXX..XXXXXXX | ||
142 | --- /dev/null | ||
143 | +++ b/tests/qemu-iotests/305.out | ||
144 | @@ -XXX,XX +XXX,XX @@ | ||
145 | +QA output created by 305 | ||
146 | +### Create the image | ||
147 | +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 | ||
148 | +### Fill the first refcount block and one data cluster from the second | ||
149 | +wrote 126976/126976 bytes at offset 0 | ||
150 | +124 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) | ||
151 | +### Discard two of the last data clusters, leave one in the middle | ||
152 | +discard 1024/1024 bytes at offset 123904 | ||
153 | +1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) | ||
154 | +discard 1024/1024 bytes at offset 125952 | ||
155 | +1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) | ||
156 | +### Corrupt the offset of the second refcount block | ||
157 | +### Try to allocate the discarded clusters again | ||
158 | +qcow2: Marking image as corrupt: Refblock offset 0x20600 unaligned (reftable index: 0x1); further corruption events will be suppressed | ||
159 | +write failed: Input/output error | ||
160 | +*** done | ||
161 | diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group | ||
162 | index XXXXXXX..XXXXXXX 100644 | ||
163 | --- a/tests/qemu-iotests/group | ||
164 | +++ b/tests/qemu-iotests/group | ||
165 | @@ -XXX,XX +XXX,XX @@ | ||
166 | 302 quick | ||
167 | 303 rw quick | ||
168 | 304 rw quick | ||
169 | +305 rw quick | ||
170 | -- | ||
171 | 2.26.2 | ||
172 | |||
173 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | From: Alberto Garcia <berto@igalia.com> | ||
2 | 1 | ||
3 | In the past, when a new cluster was allocated the l2meta structure was | ||
4 | a variable in the stack so it was necessary to have a way to tell | ||
5 | whether it had been initialized and contained valid data or not. The | ||
6 | nb_clusters field was used for this purpose. Since commit f50f88b9fe | ||
7 | this is no longer the case, l2meta (nowadays a pointer to a list) is | ||
8 | only allocated when needed and nb_clusters is guaranteed to be > 0 so | ||
9 | this check is unnecessary. | ||
10 | |||
11 | Signed-off-by: Alberto Garcia <berto@igalia.com> | ||
12 | Message-Id: <ab0b67c29c7ba26e598db35f12aa5ab5982539c1.1599150873.git.berto@igalia.com> | ||
13 | Signed-off-by: Max Reitz <mreitz@redhat.com> | ||
14 | --- | ||
15 | block/qcow2.c | 4 +--- | ||
16 | 1 file changed, 1 insertion(+), 3 deletions(-) | ||
17 | |||
18 | diff --git a/block/qcow2.c b/block/qcow2.c | ||
19 | index XXXXXXX..XXXXXXX 100644 | ||
20 | --- a/block/qcow2.c | ||
21 | +++ b/block/qcow2.c | ||
22 | @@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_handle_l2meta(BlockDriverState *bs, | ||
23 | } | ||
24 | |||
25 | /* Take the request off the list of running requests */ | ||
26 | - if (l2meta->nb_clusters != 0) { | ||
27 | - QLIST_REMOVE(l2meta, next_in_flight); | ||
28 | - } | ||
29 | + QLIST_REMOVE(l2meta, next_in_flight); | ||
30 | |||
31 | qemu_co_queue_restart_all(&l2meta->dependent_requests); | ||
32 | |||
33 | -- | ||
34 | 2.26.2 | ||
35 | |||
36 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | From: Alberto Garcia <berto@igalia.com> | ||
2 | 1 | ||
3 | The current text corresponds to an earlier, simpler version of this | ||
4 | function and it does not explain how it works now. | ||
5 | |||
6 | Signed-off-by: Alberto Garcia <berto@igalia.com> | ||
7 | Message-Id: <bb5bd06f07c5a05b0818611de0d06ec5b66c8df3.1599150873.git.berto@igalia.com> | ||
8 | Signed-off-by: Max Reitz <mreitz@redhat.com> | ||
9 | --- | ||
10 | block/qcow2-cluster.c | 24 ++++++++++++++---------- | ||
11 | 1 file changed, 14 insertions(+), 10 deletions(-) | ||
12 | |||
13 | diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c | ||
14 | index XXXXXXX..XXXXXXX 100644 | ||
15 | --- a/block/qcow2-cluster.c | ||
16 | +++ b/block/qcow2-cluster.c | ||
17 | @@ -XXX,XX +XXX,XX @@ out: | ||
18 | } | ||
19 | |||
20 | /* | ||
21 | - * alloc_cluster_offset | ||
22 | + * For a given area on the virtual disk defined by @offset and @bytes, | ||
23 | + * find the corresponding area on the qcow2 image, allocating new | ||
24 | + * clusters (or subclusters) if necessary. The result can span a | ||
25 | + * combination of allocated and previously unallocated clusters. | ||
26 | * | ||
27 | - * For a given offset on the virtual disk, find the cluster offset in qcow2 | ||
28 | - * file. If the offset is not found, allocate a new cluster. | ||
29 | + * On return, @host_offset is set to the beginning of the requested | ||
30 | + * area. This area is guaranteed to be contiguous on the qcow2 file | ||
31 | + * but it can be smaller than initially requested. In this case @bytes | ||
32 | + * is updated with the actual size. | ||
33 | * | ||
34 | - * If the cluster was already allocated, m->nb_clusters is set to 0 and | ||
35 | - * other fields in m are meaningless. | ||
36 | - * | ||
37 | - * If the cluster is newly allocated, m->nb_clusters is set to the number of | ||
38 | - * contiguous clusters that have been allocated. In this case, the other | ||
39 | - * fields of m are valid and contain information about the first allocated | ||
40 | - * cluster. | ||
41 | + * If any clusters or subclusters were allocated then @m contains a | ||
42 | + * list with the information of all the affected regions. Note that | ||
43 | + * this can happen regardless of whether this function succeeds or | ||
44 | + * not. The caller is responsible for updating the L2 metadata of the | ||
45 | + * allocated clusters (on success) or freeing them (on failure), and | ||
46 | + * for clearing the contents of @m afterwards in both cases. | ||
47 | * | ||
48 | * If the request conflicts with another write request in flight, the coroutine | ||
49 | * is queued and will be reentered when the dependency has completed. | ||
50 | -- | ||
51 | 2.26.2 | ||
52 | |||
53 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | From: Yi Li <yili@winhong.com> | ||
2 | 1 | ||
3 | Signed-off-by: Yi Li <yili@winhong.com> | ||
4 | Message-Id: <20200819013607.32280-1-yili@winhong.com> | ||
5 | Reviewed-by: Alberto Garcia <berto@igalia.com> | ||
6 | Reviewed-by: Stefano Garzarella <sgarzare@redhat.com> | ||
7 | Signed-off-by: Max Reitz <mreitz@redhat.com> | ||
8 | --- | ||
9 | qemu-img.c | 10 +++++----- | ||
10 | 1 file changed, 5 insertions(+), 5 deletions(-) | ||
11 | |||
12 | diff --git a/qemu-img.c b/qemu-img.c | ||
13 | index XXXXXXX..XXXXXXX 100644 | ||
14 | --- a/qemu-img.c | ||
15 | +++ b/qemu-img.c | ||
16 | @@ -XXX,XX +XXX,XX @@ static int is_allocated_sectors(const uint8_t *buf, int n, int *pnum, | ||
17 | *pnum = 0; | ||
18 | return 0; | ||
19 | } | ||
20 | - is_zero = buffer_is_zero(buf, 512); | ||
21 | + is_zero = buffer_is_zero(buf, BDRV_SECTOR_SIZE); | ||
22 | for(i = 1; i < n; i++) { | ||
23 | - buf += 512; | ||
24 | - if (is_zero != buffer_is_zero(buf, 512)) { | ||
25 | + buf += BDRV_SECTOR_SIZE; | ||
26 | + if (is_zero != buffer_is_zero(buf, BDRV_SECTOR_SIZE)) { | ||
27 | break; | ||
28 | } | ||
29 | } | ||
30 | @@ -XXX,XX +XXX,XX @@ static int img_convert(int argc, char **argv) | ||
31 | } | ||
32 | } | ||
33 | |||
34 | - qemu_opt_set_number(opts, BLOCK_OPT_SIZE, s.total_sectors * 512, | ||
35 | - &error_abort); | ||
36 | + qemu_opt_set_number(opts, BLOCK_OPT_SIZE, | ||
37 | + s.total_sectors * BDRV_SECTOR_SIZE, &error_abort); | ||
38 | ret = add_old_style_options(out_fmt, opts, out_baseimg, NULL); | ||
39 | if (ret < 0) { | ||
40 | goto out; | ||
41 | -- | ||
42 | 2.26.2 | ||
43 | |||
44 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | From: Thomas Huth <thuth@redhat.com> | ||
2 | 1 | ||
3 | The test_stream_parallel test still occasionally fails in the CI. | ||
4 | Thus let's disable it during "make check" for now so that it does | ||
5 | not cause trouble during merge tests. We can enable it again once | ||
6 | the problem has been resolved. | ||
7 | |||
8 | Signed-off-by: Thomas Huth <thuth@redhat.com> | ||
9 | Message-Id: <20200907113824.134788-1-thuth@redhat.com> | ||
10 | Signed-off-by: Max Reitz <mreitz@redhat.com> | ||
11 | --- | ||
12 | tests/check-block.sh | 3 +++ | ||
13 | tests/qemu-iotests/030 | 2 ++ | ||
14 | 2 files changed, 5 insertions(+) | ||
15 | |||
16 | diff --git a/tests/check-block.sh b/tests/check-block.sh | ||
17 | index XXXXXXX..XXXXXXX 100755 | ||
18 | --- a/tests/check-block.sh | ||
19 | +++ b/tests/check-block.sh | ||
20 | @@ -XXX,XX +XXX,XX @@ fi | ||
21 | |||
22 | cd tests/qemu-iotests | ||
23 | |||
24 | +# QEMU_CHECK_BLOCK_AUTO is used to disable some unstable sub-tests | ||
25 | +export QEMU_CHECK_BLOCK_AUTO=1 | ||
26 | + | ||
27 | ret=0 | ||
28 | for fmt in $format_list ; do | ||
29 | ./check -makecheck -$fmt $group || ret=1 | ||
30 | diff --git a/tests/qemu-iotests/030 b/tests/qemu-iotests/030 | ||
31 | index XXXXXXX..XXXXXXX 100755 | ||
32 | --- a/tests/qemu-iotests/030 | ||
33 | +++ b/tests/qemu-iotests/030 | ||
34 | @@ -XXX,XX +XXX,XX @@ | ||
35 | import time | ||
36 | import os | ||
37 | import iotests | ||
38 | +import unittest | ||
39 | from iotests import qemu_img, qemu_io | ||
40 | |||
41 | backing_img = os.path.join(iotests.test_dir, 'backing.img') | ||
42 | @@ -XXX,XX +XXX,XX @@ class TestParallelOps(iotests.QMPTestCase): | ||
43 | |||
44 | # Test that it's possible to run several block-stream operations | ||
45 | # in parallel in the same snapshot chain | ||
46 | + @unittest.skipIf(os.environ.get('QEMU_CHECK_BLOCK_AUTO'), 'disabled in CI') | ||
47 | def test_stream_parallel(self): | ||
48 | self.assert_no_active_block_jobs() | ||
49 | |||
50 | -- | ||
51 | 2.26.2 | ||
52 | |||
53 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | From: Swapnil Ingle <swapnil.ingle@nutanix.com> | ||
2 | 1 | ||
3 | block/vhdx uses qemu block layer where sector size is always 512 bytes. | ||
4 | This may have issues with 4K logical sector sized vhdx image. | ||
5 | |||
6 | For e.g qemu-img convert on such images fails with following assert: | ||
7 | |||
8 | $qemu-img convert -f vhdx -O raw 4KTest1.vhdx test.raw | ||
9 | qemu-img: util/iov.c:388: qiov_slice: Assertion `offset + len <= | ||
10 | qiov->size' failed. | ||
11 | Aborted | ||
12 | |||
13 | This patch adds an check to return ENOTSUP for vhdx images which | ||
14 | have logical sector size other than 512 bytes. | ||
15 | |||
16 | Signed-off-by: Swapnil Ingle <swapnil.ingle@nutanix.com> | ||
17 | Message-Id: <1596794594-44531-1-git-send-email-swapnil.ingle@nutanix.com> | ||
18 | Signed-off-by: Max Reitz <mreitz@redhat.com> | ||
19 | --- | ||
20 | block/vhdx.c | 6 +++--- | ||
21 | 1 file changed, 3 insertions(+), 3 deletions(-) | ||
22 | |||
23 | diff --git a/block/vhdx.c b/block/vhdx.c | ||
24 | index XXXXXXX..XXXXXXX 100644 | ||
25 | --- a/block/vhdx.c | ||
26 | +++ b/block/vhdx.c | ||
27 | @@ -XXX,XX +XXX,XX @@ static int vhdx_parse_metadata(BlockDriverState *bs, BDRVVHDXState *s) | ||
28 | goto exit; | ||
29 | } | ||
30 | |||
31 | - /* only 2 supported sector sizes */ | ||
32 | - if (s->logical_sector_size != 512 && s->logical_sector_size != 4096) { | ||
33 | - ret = -EINVAL; | ||
34 | + /* Currently we only support 512 */ | ||
35 | + if (s->logical_sector_size != 512) { | ||
36 | + ret = -ENOTSUP; | ||
37 | goto exit; | ||
38 | } | ||
39 | |||
40 | -- | ||
41 | 2.26.2 | ||
42 | |||
43 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | From: Alberto Garcia <berto@igalia.com> | ||
2 | 1 | ||
3 | If qcow2_alloc_cluster_offset() or qcow2_alloc_cluster_link_l2() fail | ||
4 | then this function simply returns the error code, potentially leaking | ||
5 | the QCowL2Meta structure and leaving stale items in s->cluster_allocs. | ||
6 | |||
7 | A second problem is that this function calls qcow2_free_any_clusters() | ||
8 | on failure but passing a host cluster offset instead of an L2 entry. | ||
9 | Luckily for normal uncompressed clusters a raw offset also works like | ||
10 | a valid L2 entry so it works just the same, but we should be using | ||
11 | qcow2_free_clusters() instead. | ||
12 | |||
13 | This patch fixes both problems by using qcow2_handle_l2meta(). | ||
14 | |||
15 | Signed-off-by: Alberto Garcia <berto@igalia.com> | ||
16 | Message-Id: <cd3a6b9abd43f9c0b60be413d760f0cacc67eb66.1599573989.git.berto@igalia.com> | ||
17 | Reviewed-by: Kevin Wolf <kwolf@redhat.com> | ||
18 | Signed-off-by: Max Reitz <mreitz@redhat.com> | ||
19 | --- | ||
20 | block/qcow2.c | 40 +++++++++++++++++----------------------- | ||
21 | 1 file changed, 17 insertions(+), 23 deletions(-) | ||
22 | |||
23 | diff --git a/block/qcow2.c b/block/qcow2.c | ||
24 | index XXXXXXX..XXXXXXX 100644 | ||
25 | --- a/block/qcow2.c | ||
26 | +++ b/block/qcow2.c | ||
27 | @@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_handle_l2meta(BlockDriverState *bs, | ||
28 | QCowL2Meta *next; | ||
29 | |||
30 | if (link_l2) { | ||
31 | - assert(!l2meta->prealloc); | ||
32 | ret = qcow2_alloc_cluster_link_l2(bs, l2meta); | ||
33 | if (ret) { | ||
34 | goto out; | ||
35 | @@ -XXX,XX +XXX,XX @@ static int coroutine_fn preallocate_co(BlockDriverState *bs, uint64_t offset, | ||
36 | int64_t file_length; | ||
37 | unsigned int cur_bytes; | ||
38 | int ret; | ||
39 | - QCowL2Meta *meta; | ||
40 | + QCowL2Meta *meta = NULL, *m; | ||
41 | |||
42 | assert(offset <= new_length); | ||
43 | bytes = new_length - offset; | ||
44 | @@ -XXX,XX +XXX,XX @@ static int coroutine_fn preallocate_co(BlockDriverState *bs, uint64_t offset, | ||
45 | &host_offset, &meta); | ||
46 | if (ret < 0) { | ||
47 | error_setg_errno(errp, -ret, "Allocating clusters failed"); | ||
48 | - return ret; | ||
49 | + goto out; | ||
50 | } | ||
51 | |||
52 | - while (meta) { | ||
53 | - QCowL2Meta *next = meta->next; | ||
54 | - meta->prealloc = true; | ||
55 | - | ||
56 | - ret = qcow2_alloc_cluster_link_l2(bs, meta); | ||
57 | - if (ret < 0) { | ||
58 | - error_setg_errno(errp, -ret, "Mapping clusters failed"); | ||
59 | - qcow2_free_any_clusters(bs, meta->alloc_offset, | ||
60 | - meta->nb_clusters, QCOW2_DISCARD_NEVER); | ||
61 | - return ret; | ||
62 | - } | ||
63 | - | ||
64 | - /* There are no dependent requests, but we need to remove our | ||
65 | - * request from the list of in-flight requests */ | ||
66 | - QLIST_REMOVE(meta, next_in_flight); | ||
67 | + for (m = meta; m != NULL; m = m->next) { | ||
68 | + m->prealloc = true; | ||
69 | + } | ||
70 | |||
71 | - g_free(meta); | ||
72 | - meta = next; | ||
73 | + ret = qcow2_handle_l2meta(bs, &meta, true); | ||
74 | + if (ret < 0) { | ||
75 | + error_setg_errno(errp, -ret, "Mapping clusters failed"); | ||
76 | + goto out; | ||
77 | } | ||
78 | |||
79 | /* TODO Preallocate data if requested */ | ||
80 | @@ -XXX,XX +XXX,XX @@ static int coroutine_fn preallocate_co(BlockDriverState *bs, uint64_t offset, | ||
81 | file_length = bdrv_getlength(s->data_file->bs); | ||
82 | if (file_length < 0) { | ||
83 | error_setg_errno(errp, -file_length, "Could not get file size"); | ||
84 | - return file_length; | ||
85 | + ret = file_length; | ||
86 | + goto out; | ||
87 | } | ||
88 | |||
89 | if (host_offset + cur_bytes > file_length) { | ||
90 | @@ -XXX,XX +XXX,XX @@ static int coroutine_fn preallocate_co(BlockDriverState *bs, uint64_t offset, | ||
91 | ret = bdrv_co_truncate(s->data_file, host_offset + cur_bytes, false, | ||
92 | mode, 0, errp); | ||
93 | if (ret < 0) { | ||
94 | - return ret; | ||
95 | + goto out; | ||
96 | } | ||
97 | } | ||
98 | |||
99 | - return 0; | ||
100 | + ret = 0; | ||
101 | + | ||
102 | +out: | ||
103 | + qcow2_handle_l2meta(bs, &meta, false); | ||
104 | + return ret; | ||
105 | } | ||
106 | |||
107 | /* qcow2_refcount_metadata_size: | ||
108 | -- | ||
109 | 2.26.2 | ||
110 | |||
111 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | From: Alberto Garcia <berto@igalia.com> | ||
2 | 1 | ||
3 | This function takes an L2 entry and a number of clusters to free. | ||
4 | Although in principle it can free any type of cluster (using the L2 | ||
5 | entry to determine its type) in practice the API is broken because | ||
6 | compressed clusters have a variable size and there is no way to free | ||
7 | more than one without having the L2 entry of each one of them. | ||
8 | |||
9 | The good news all callers are passing nb_clusters=1 so we can simply | ||
10 | get rid of that parameter. | ||
11 | |||
12 | Signed-off-by: Alberto Garcia <berto@igalia.com> | ||
13 | Message-Id: <77cea0f4616f921d37e971b3c5b18a2faa24b173.1599573989.git.berto@igalia.com> | ||
14 | Reviewed-by: Kevin Wolf <kwolf@redhat.com> | ||
15 | Signed-off-by: Max Reitz <mreitz@redhat.com> | ||
16 | --- | ||
17 | block/qcow2.h | 4 ++-- | ||
18 | block/qcow2-cluster.c | 6 +++--- | ||
19 | block/qcow2-refcount.c | 8 ++++---- | ||
20 | 3 files changed, 9 insertions(+), 9 deletions(-) | ||
21 | |||
22 | diff --git a/block/qcow2.h b/block/qcow2.h | ||
23 | index XXXXXXX..XXXXXXX 100644 | ||
24 | --- a/block/qcow2.h | ||
25 | +++ b/block/qcow2.h | ||
26 | @@ -XXX,XX +XXX,XX @@ int64_t qcow2_alloc_bytes(BlockDriverState *bs, int size); | ||
27 | void qcow2_free_clusters(BlockDriverState *bs, | ||
28 | int64_t offset, int64_t size, | ||
29 | enum qcow2_discard_type type); | ||
30 | -void qcow2_free_any_clusters(BlockDriverState *bs, uint64_t l2_entry, | ||
31 | - int nb_clusters, enum qcow2_discard_type type); | ||
32 | +void qcow2_free_any_cluster(BlockDriverState *bs, uint64_t l2_entry, | ||
33 | + enum qcow2_discard_type type); | ||
34 | |||
35 | int qcow2_update_snapshot_refcount(BlockDriverState *bs, | ||
36 | int64_t l1_table_offset, int l1_size, int addend); | ||
37 | diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c | ||
38 | index XXXXXXX..XXXXXXX 100644 | ||
39 | --- a/block/qcow2-cluster.c | ||
40 | +++ b/block/qcow2-cluster.c | ||
41 | @@ -XXX,XX +XXX,XX @@ int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m) | ||
42 | */ | ||
43 | if (!m->keep_old_clusters && j != 0) { | ||
44 | for (i = 0; i < j; i++) { | ||
45 | - qcow2_free_any_clusters(bs, old_cluster[i], 1, QCOW2_DISCARD_NEVER); | ||
46 | + qcow2_free_any_cluster(bs, old_cluster[i], QCOW2_DISCARD_NEVER); | ||
47 | } | ||
48 | } | ||
49 | |||
50 | @@ -XXX,XX +XXX,XX @@ static int discard_in_l2_slice(BlockDriverState *bs, uint64_t offset, | ||
51 | set_l2_bitmap(s, l2_slice, l2_index + i, new_l2_bitmap); | ||
52 | } | ||
53 | /* Then decrease the refcount */ | ||
54 | - qcow2_free_any_clusters(bs, old_l2_entry, 1, type); | ||
55 | + qcow2_free_any_cluster(bs, old_l2_entry, type); | ||
56 | } | ||
57 | |||
58 | qcow2_cache_put(s->l2_table_cache, (void **) &l2_slice); | ||
59 | @@ -XXX,XX +XXX,XX @@ static int zero_in_l2_slice(BlockDriverState *bs, uint64_t offset, | ||
60 | |||
61 | qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_slice); | ||
62 | if (unmap) { | ||
63 | - qcow2_free_any_clusters(bs, old_l2_entry, 1, QCOW2_DISCARD_REQUEST); | ||
64 | + qcow2_free_any_cluster(bs, old_l2_entry, QCOW2_DISCARD_REQUEST); | ||
65 | } | ||
66 | set_l2_entry(s, l2_slice, l2_index + i, new_l2_entry); | ||
67 | if (has_subclusters(s)) { | ||
68 | diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c | ||
69 | index XXXXXXX..XXXXXXX 100644 | ||
70 | --- a/block/qcow2-refcount.c | ||
71 | +++ b/block/qcow2-refcount.c | ||
72 | @@ -XXX,XX +XXX,XX @@ void qcow2_free_clusters(BlockDriverState *bs, | ||
73 | * Free a cluster using its L2 entry (handles clusters of all types, e.g. | ||
74 | * normal cluster, compressed cluster, etc.) | ||
75 | */ | ||
76 | -void qcow2_free_any_clusters(BlockDriverState *bs, uint64_t l2_entry, | ||
77 | - int nb_clusters, enum qcow2_discard_type type) | ||
78 | +void qcow2_free_any_cluster(BlockDriverState *bs, uint64_t l2_entry, | ||
79 | + enum qcow2_discard_type type) | ||
80 | { | ||
81 | BDRVQcow2State *s = bs->opaque; | ||
82 | QCow2ClusterType ctype = qcow2_get_cluster_type(bs, l2_entry); | ||
83 | @@ -XXX,XX +XXX,XX @@ void qcow2_free_any_clusters(BlockDriverState *bs, uint64_t l2_entry, | ||
84 | ctype == QCOW2_CLUSTER_ZERO_ALLOC)) | ||
85 | { | ||
86 | bdrv_pdiscard(s->data_file, l2_entry & L2E_OFFSET_MASK, | ||
87 | - nb_clusters << s->cluster_bits); | ||
88 | + s->cluster_size); | ||
89 | } | ||
90 | return; | ||
91 | } | ||
92 | @@ -XXX,XX +XXX,XX @@ void qcow2_free_any_clusters(BlockDriverState *bs, uint64_t l2_entry, | ||
93 | l2_entry & L2E_OFFSET_MASK); | ||
94 | } else { | ||
95 | qcow2_free_clusters(bs, l2_entry & L2E_OFFSET_MASK, | ||
96 | - nb_clusters << s->cluster_bits, type); | ||
97 | + s->cluster_size, type); | ||
98 | } | ||
99 | break; | ||
100 | case QCOW2_CLUSTER_ZERO_PLAIN: | ||
101 | -- | ||
102 | 2.26.2 | ||
103 | |||
104 | diff view generated by jsdifflib |
1 | From: Alberto Garcia <berto@igalia.com> | 1 | From: Mark Mielke <mark.mielke@gmail.com> |
---|---|---|---|
2 | 2 | ||
3 | This function checks the current status of a (sub)cluster in order to | 3 | The code that introduced "virtio-blk: Configure all host notifiers in |
4 | see if an unaligned 'write zeroes' request can be done efficiently by | 4 | a single MR transaction" introduced a second loop variable to perform |
5 | simply updating the L2 metadata and without having to write actual | 5 | cleanup in second loop, but mistakenly still refers to the first |
6 | zeroes to disk. | 6 | loop variable within the second loop body. |
7 | 7 | ||
8 | If the situation does not allow using the fast path then the function | 8 | Fixes: d0267da61489 ("virtio-blk: Configure all host notifiers in a single MR transaction") |
9 | returns -ENOTSUP and the caller falls back to writing zeroes. | 9 | Signed-off-by: Mark Mielke <mark.mielke@gmail.com> |
10 | 10 | Message-id: CALm7yL08qarOu0dnQkTN+pa=BSRC92g31YpQQNDeAiT4yLZWQQ@mail.gmail.com | |
11 | If can happen however that the aforementioned check returns an actual | 11 | Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> |
12 | error code so in this case we should pass it to the caller. | ||
13 | |||
14 | Signed-off-by: Alberto Garcia <berto@igalia.com> | ||
15 | Message-Id: <20200909123739.719-1-berto@igalia.com> | ||
16 | Reviewed-by: Eric Blake <eblake@redhat.com> | ||
17 | Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com> | ||
18 | Reviewed-by: Kevin Wolf <kwolf@redhat.com> | ||
19 | Signed-off-by: Max Reitz <mreitz@redhat.com> | ||
20 | --- | 12 | --- |
21 | block/qcow2.c | 2 +- | 13 | hw/block/dataplane/virtio-blk.c | 2 +- |
22 | 1 file changed, 1 insertion(+), 1 deletion(-) | 14 | 1 file changed, 1 insertion(+), 1 deletion(-) |
23 | 15 | ||
24 | diff --git a/block/qcow2.c b/block/qcow2.c | 16 | diff --git a/hw/block/dataplane/virtio-blk.c b/hw/block/dataplane/virtio-blk.c |
25 | index XXXXXXX..XXXXXXX 100644 | 17 | index XXXXXXX..XXXXXXX 100644 |
26 | --- a/block/qcow2.c | 18 | --- a/hw/block/dataplane/virtio-blk.c |
27 | +++ b/block/qcow2.c | 19 | +++ b/hw/block/dataplane/virtio-blk.c |
28 | @@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_pwrite_zeroes(BlockDriverState *bs, | 20 | @@ -XXX,XX +XXX,XX @@ int virtio_blk_data_plane_start(VirtIODevice *vdev) |
29 | type != QCOW2_SUBCLUSTER_ZERO_PLAIN && | 21 | memory_region_transaction_commit(); |
30 | type != QCOW2_SUBCLUSTER_ZERO_ALLOC)) { | 22 | |
31 | qemu_co_mutex_unlock(&s->lock); | 23 | while (j--) { |
32 | - return -ENOTSUP; | 24 | - virtio_bus_cleanup_host_notifier(VIRTIO_BUS(qbus), i); |
33 | + return ret < 0 ? ret : -ENOTSUP; | 25 | + virtio_bus_cleanup_host_notifier(VIRTIO_BUS(qbus), j); |
26 | } | ||
27 | goto fail_host_notifiers; | ||
34 | } | 28 | } |
35 | } else { | ||
36 | qemu_co_mutex_lock(&s->lock); | ||
37 | -- | 29 | -- |
38 | 2.26.2 | 30 | 2.33.1 |
39 | 31 | ||
40 | 32 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | From: John Snow <jsnow@redhat.com> | ||
2 | 1 | ||
3 | This saw its last use in 4bfb274165ba. | ||
4 | |||
5 | Signed-off-by: John Snow <jsnow@redhat.com> | ||
6 | Message-Id: <20200806211345.2925343-2-jsnow@redhat.com> | ||
7 | Signed-off-by: Max Reitz <mreitz@redhat.com> | ||
8 | --- | ||
9 | block/rbd.c | 42 ------------------------------------------ | ||
10 | 1 file changed, 42 deletions(-) | ||
11 | |||
12 | diff --git a/block/rbd.c b/block/rbd.c | ||
13 | index XXXXXXX..XXXXXXX 100644 | ||
14 | --- a/block/rbd.c | ||
15 | +++ b/block/rbd.c | ||
16 | @@ -XXX,XX +XXX,XX @@ static void qemu_rbd_memset(RADOSCB *rcb, int64_t offs) | ||
17 | } | ||
18 | } | ||
19 | |||
20 | -static QemuOptsList runtime_opts = { | ||
21 | - .name = "rbd", | ||
22 | - .head = QTAILQ_HEAD_INITIALIZER(runtime_opts.head), | ||
23 | - .desc = { | ||
24 | - { | ||
25 | - .name = "pool", | ||
26 | - .type = QEMU_OPT_STRING, | ||
27 | - .help = "Rados pool name", | ||
28 | - }, | ||
29 | - { | ||
30 | - .name = "namespace", | ||
31 | - .type = QEMU_OPT_STRING, | ||
32 | - .help = "Rados namespace name in the pool", | ||
33 | - }, | ||
34 | - { | ||
35 | - .name = "image", | ||
36 | - .type = QEMU_OPT_STRING, | ||
37 | - .help = "Image name in the pool", | ||
38 | - }, | ||
39 | - { | ||
40 | - .name = "conf", | ||
41 | - .type = QEMU_OPT_STRING, | ||
42 | - .help = "Rados config file location", | ||
43 | - }, | ||
44 | - { | ||
45 | - .name = "snapshot", | ||
46 | - .type = QEMU_OPT_STRING, | ||
47 | - .help = "Ceph snapshot name", | ||
48 | - }, | ||
49 | - { | ||
50 | - /* maps to 'id' in rados_create() */ | ||
51 | - .name = "user", | ||
52 | - .type = QEMU_OPT_STRING, | ||
53 | - .help = "Rados id name", | ||
54 | - }, | ||
55 | - /* | ||
56 | - * server.* extracted manually, see qemu_rbd_mon_host() | ||
57 | - */ | ||
58 | - { /* end of list */ } | ||
59 | - }, | ||
60 | -}; | ||
61 | - | ||
62 | /* FIXME Deprecate and remove keypairs or make it available in QMP. */ | ||
63 | static int qemu_rbd_do_create(BlockdevCreateOptions *options, | ||
64 | const char *keypairs, const char *password_secret, | ||
65 | -- | ||
66 | 2.26.2 | ||
67 | |||
68 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | From: John Snow <jsnow@redhat.com> | ||
2 | 1 | ||
3 | Introduced by d85f4222b468, | ||
4 | These were seemingly never used at all. | ||
5 | |||
6 | Signed-off-by: John Snow <jsnow@redhat.com> | ||
7 | Message-Id: <20200806211345.2925343-3-jsnow@redhat.com> | ||
8 | Signed-off-by: Max Reitz <mreitz@redhat.com> | ||
9 | --- | ||
10 | block/qcow.c | 9 --------- | ||
11 | 1 file changed, 9 deletions(-) | ||
12 | |||
13 | diff --git a/block/qcow.c b/block/qcow.c | ||
14 | index XXXXXXX..XXXXXXX 100644 | ||
15 | --- a/block/qcow.c | ||
16 | +++ b/block/qcow.c | ||
17 | @@ -XXX,XX +XXX,XX @@ static int qcow_probe(const uint8_t *buf, int buf_size, const char *filename) | ||
18 | return 0; | ||
19 | } | ||
20 | |||
21 | -static QemuOptsList qcow_runtime_opts = { | ||
22 | - .name = "qcow", | ||
23 | - .head = QTAILQ_HEAD_INITIALIZER(qcow_runtime_opts.head), | ||
24 | - .desc = { | ||
25 | - BLOCK_CRYPTO_OPT_DEF_QCOW_KEY_SECRET("encrypt."), | ||
26 | - { /* end of list */ } | ||
27 | - }, | ||
28 | -}; | ||
29 | - | ||
30 | static int qcow_open(BlockDriverState *bs, QDict *options, int flags, | ||
31 | Error **errp) | ||
32 | { | ||
33 | -- | ||
34 | 2.26.2 | ||
35 | |||
36 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | From: Alberto Garcia <berto@igalia.com> | ||
2 | 1 | ||
3 | This function preallocates metadata structures and then extends the | ||
4 | image to its new size, but that new size calculation is wrong because | ||
5 | it doesn't take into account that the host_offset variable is always | ||
6 | cluster-aligned. | ||
7 | |||
8 | This problem can be reproduced with preallocation=metadata when the | ||
9 | original size is not cluster-aligned but the new size is. In this case | ||
10 | the final image size will be shorter than expected. | ||
11 | |||
12 | qemu-img create -f qcow2 img.qcow2 31k | ||
13 | qemu-img resize --preallocation=metadata img.qcow2 128k | ||
14 | |||
15 | Signed-off-by: Alberto Garcia <berto@igalia.com> | ||
16 | Message-Id: <adeb8b059917b141d5f5b3bd2a016262d3052c79.1599833007.git.berto@igalia.com> | ||
17 | Reviewed-by: Max Reitz <mreitz@redhat.com> | ||
18 | [mreitz: Mark compat=0.10 unsupported for iotest 125] | ||
19 | Signed-off-by: Max Reitz <mreitz@redhat.com> | ||
20 | --- | ||
21 | block/qcow2.c | 1 + | ||
22 | tests/qemu-iotests/125 | 44 ++++++++++++++++++++++---------------- | ||
23 | tests/qemu-iotests/125.out | 28 ++++++++++++++++++++++-- | ||
24 | 3 files changed, 53 insertions(+), 20 deletions(-) | ||
25 | |||
26 | diff --git a/block/qcow2.c b/block/qcow2.c | ||
27 | index XXXXXXX..XXXXXXX 100644 | ||
28 | --- a/block/qcow2.c | ||
29 | +++ b/block/qcow2.c | ||
30 | @@ -XXX,XX +XXX,XX @@ static int coroutine_fn preallocate_co(BlockDriverState *bs, uint64_t offset, | ||
31 | error_setg_errno(errp, -ret, "Allocating clusters failed"); | ||
32 | goto out; | ||
33 | } | ||
34 | + host_offset += offset_into_cluster(s, offset); | ||
35 | |||
36 | for (m = meta; m != NULL; m = m->next) { | ||
37 | m->prealloc = true; | ||
38 | diff --git a/tests/qemu-iotests/125 b/tests/qemu-iotests/125 | ||
39 | index XXXXXXX..XXXXXXX 100755 | ||
40 | --- a/tests/qemu-iotests/125 | ||
41 | +++ b/tests/qemu-iotests/125 | ||
42 | @@ -XXX,XX +XXX,XX @@ get_image_size_on_host() | ||
43 | |||
44 | _supported_fmt qcow2 | ||
45 | _supported_proto file | ||
46 | +# Growing a file with a backing file (without preallocation=full or | ||
47 | +# =falloc) requires zeroing the newly added area, which is impossible | ||
48 | +# to do quickly for v2 images, and hence is unsupported. | ||
49 | +_unsupported_imgopts 'compat=0.10' | ||
50 | |||
51 | if [ -z "$TEST_IMG_FILE" ]; then | ||
52 | TEST_IMG_FILE=$TEST_IMG | ||
53 | @@ -XXX,XX +XXX,XX @@ done | ||
54 | $QEMU_IMG create -f raw "$TEST_IMG.base" 128k | _filter_img_create | ||
55 | $QEMU_IO -c 'write -q -P 1 0 128k' -f raw "$TEST_IMG.base" | ||
56 | for orig_size in 31k 33k; do | ||
57 | - echo "--- Resizing image from $orig_size to 96k ---" | ||
58 | - _make_test_img -F raw -b "$TEST_IMG.base" -o cluster_size=64k "$orig_size" | ||
59 | - $QEMU_IMG resize -f "$IMGFMT" --preallocation=full "$TEST_IMG" 96k | ||
60 | - # The first part of the image should contain data from the backing file | ||
61 | - $QEMU_IO -c "read -q -P 1 0 ${orig_size}" "$TEST_IMG" | ||
62 | - # The resized part of the image should contain zeroes | ||
63 | - $QEMU_IO -c "read -q -P 0 ${orig_size} 63k" "$TEST_IMG" | ||
64 | - # If the image does not have an external data file we can also verify its | ||
65 | - # actual size. The resized image should have 7 clusters: | ||
66 | - # header, L1 table, L2 table, refcount table, refcount block, 2 data clusters | ||
67 | - if ! _get_data_file "$TEST_IMG" > /dev/null; then | ||
68 | - expected_file_length=$((65536 * 7)) | ||
69 | - file_length=$(stat -c '%s' "$TEST_IMG_FILE") | ||
70 | - if [ "$file_length" != "$expected_file_length" ]; then | ||
71 | - echo "ERROR: file length $file_length (expected $expected_file_length)" | ||
72 | - fi | ||
73 | - fi | ||
74 | - echo | ||
75 | + for dst_size in 96k 128k; do | ||
76 | + for prealloc in metadata full; do | ||
77 | + echo "--- Resizing image from $orig_size to $dst_size (preallocation=$prealloc) ---" | ||
78 | + _make_test_img -F raw -b "$TEST_IMG.base" -o cluster_size=64k "$orig_size" | ||
79 | + $QEMU_IMG resize -f "$IMGFMT" --preallocation="$prealloc" "$TEST_IMG" "$dst_size" | ||
80 | + # The first part of the image should contain data from the backing file | ||
81 | + $QEMU_IO -c "read -q -P 1 0 ${orig_size}" "$TEST_IMG" | ||
82 | + # The resized part of the image should contain zeroes | ||
83 | + $QEMU_IO -c "read -q -P 0 ${orig_size} 63k" "$TEST_IMG" | ||
84 | + # If the image does not have an external data file we can also verify its | ||
85 | + # actual size. The resized image should have 7 clusters: | ||
86 | + # header, L1 table, L2 table, refcount table, refcount block, 2 data clusters | ||
87 | + if ! _get_data_file "$TEST_IMG" > /dev/null; then | ||
88 | + expected_file_length=$((65536 * 7)) | ||
89 | + file_length=$(stat -c '%s' "$TEST_IMG_FILE") | ||
90 | + if [ "$file_length" != "$expected_file_length" ]; then | ||
91 | + echo "ERROR: file length $file_length (expected $expected_file_length)" | ||
92 | + fi | ||
93 | + fi | ||
94 | + echo | ||
95 | + done | ||
96 | + done | ||
97 | done | ||
98 | |||
99 | # success, all done | ||
100 | diff --git a/tests/qemu-iotests/125.out b/tests/qemu-iotests/125.out | ||
101 | index XXXXXXX..XXXXXXX 100644 | ||
102 | --- a/tests/qemu-iotests/125.out | ||
103 | +++ b/tests/qemu-iotests/125.out | ||
104 | @@ -XXX,XX +XXX,XX @@ wrote 81920/81920 bytes at offset 2048000 | ||
105 | 80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) | ||
106 | |||
107 | Formatting 'TEST_DIR/t.IMGFMT.base', fmt=raw size=131072 | ||
108 | ---- Resizing image from 31k to 96k --- | ||
109 | +--- Resizing image from 31k to 96k (preallocation=metadata) --- | ||
110 | Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=31744 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=raw | ||
111 | Image resized. | ||
112 | |||
113 | ---- Resizing image from 33k to 96k --- | ||
114 | +--- Resizing image from 31k to 96k (preallocation=full) --- | ||
115 | +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=31744 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=raw | ||
116 | +Image resized. | ||
117 | + | ||
118 | +--- Resizing image from 31k to 128k (preallocation=metadata) --- | ||
119 | +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=31744 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=raw | ||
120 | +Image resized. | ||
121 | + | ||
122 | +--- Resizing image from 31k to 128k (preallocation=full) --- | ||
123 | +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=31744 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=raw | ||
124 | +Image resized. | ||
125 | + | ||
126 | +--- Resizing image from 33k to 96k (preallocation=metadata) --- | ||
127 | +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=33792 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=raw | ||
128 | +Image resized. | ||
129 | + | ||
130 | +--- Resizing image from 33k to 96k (preallocation=full) --- | ||
131 | +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=33792 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=raw | ||
132 | +Image resized. | ||
133 | + | ||
134 | +--- Resizing image from 33k to 128k (preallocation=metadata) --- | ||
135 | +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=33792 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=raw | ||
136 | +Image resized. | ||
137 | + | ||
138 | +--- Resizing image from 33k to 128k (preallocation=full) --- | ||
139 | Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=33792 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=raw | ||
140 | Image resized. | ||
141 | |||
142 | -- | ||
143 | 2.26.2 | ||
144 | |||
145 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | From: Alberto Garcia <berto@igalia.com> | ||
2 | 1 | ||
3 | qcow2_alloc_cluster_offset() takes an (unaligned) guest offset and | ||
4 | returns the (aligned) offset of the corresponding cluster in the qcow2 | ||
5 | image. | ||
6 | |||
7 | In practice none of the callers need to know where the cluster starts | ||
8 | so this patch makes the function calculate and return the final host | ||
9 | offset directly. The function is also renamed accordingly. | ||
10 | |||
11 | See 388e581615 for a similar change to qcow2_get_cluster_offset(). | ||
12 | |||
13 | Signed-off-by: Alberto Garcia <berto@igalia.com> | ||
14 | Message-Id: <9bfef50ec9200d752413be4fc2aeb22a28378817.1599833007.git.berto@igalia.com> | ||
15 | Reviewed-by: Max Reitz <mreitz@redhat.com> | ||
16 | Signed-off-by: Max Reitz <mreitz@redhat.com> | ||
17 | --- | ||
18 | block/qcow2.h | 6 +++--- | ||
19 | block/qcow2-cluster.c | 14 ++++++++++---- | ||
20 | block/qcow2.c | 36 +++++++++++++----------------------- | ||
21 | 3 files changed, 26 insertions(+), 30 deletions(-) | ||
22 | |||
23 | diff --git a/block/qcow2.h b/block/qcow2.h | ||
24 | index XXXXXXX..XXXXXXX 100644 | ||
25 | --- a/block/qcow2.h | ||
26 | +++ b/block/qcow2.h | ||
27 | @@ -XXX,XX +XXX,XX @@ int qcow2_encrypt_sectors(BDRVQcow2State *s, int64_t sector_num, | ||
28 | int qcow2_get_host_offset(BlockDriverState *bs, uint64_t offset, | ||
29 | unsigned int *bytes, uint64_t *host_offset, | ||
30 | QCow2SubclusterType *subcluster_type); | ||
31 | -int qcow2_alloc_cluster_offset(BlockDriverState *bs, uint64_t offset, | ||
32 | - unsigned int *bytes, uint64_t *host_offset, | ||
33 | - QCowL2Meta **m); | ||
34 | +int qcow2_alloc_host_offset(BlockDriverState *bs, uint64_t offset, | ||
35 | + unsigned int *bytes, uint64_t *host_offset, | ||
36 | + QCowL2Meta **m); | ||
37 | int qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs, | ||
38 | uint64_t offset, | ||
39 | int compressed_size, | ||
40 | diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c | ||
41 | index XXXXXXX..XXXXXXX 100644 | ||
42 | --- a/block/qcow2-cluster.c | ||
43 | +++ b/block/qcow2-cluster.c | ||
44 | @@ -XXX,XX +XXX,XX @@ out: | ||
45 | * clusters (or subclusters) if necessary. The result can span a | ||
46 | * combination of allocated and previously unallocated clusters. | ||
47 | * | ||
48 | + * Note that offset may not be cluster aligned. In this case, the returned | ||
49 | + * *host_offset points to exact byte referenced by offset and therefore | ||
50 | + * isn't cluster aligned as well. | ||
51 | + * | ||
52 | * On return, @host_offset is set to the beginning of the requested | ||
53 | * area. This area is guaranteed to be contiguous on the qcow2 file | ||
54 | * but it can be smaller than initially requested. In this case @bytes | ||
55 | @@ -XXX,XX +XXX,XX @@ out: | ||
56 | * | ||
57 | * Return 0 on success and -errno in error cases | ||
58 | */ | ||
59 | -int qcow2_alloc_cluster_offset(BlockDriverState *bs, uint64_t offset, | ||
60 | - unsigned int *bytes, uint64_t *host_offset, | ||
61 | - QCowL2Meta **m) | ||
62 | +int qcow2_alloc_host_offset(BlockDriverState *bs, uint64_t offset, | ||
63 | + unsigned int *bytes, uint64_t *host_offset, | ||
64 | + QCowL2Meta **m) | ||
65 | { | ||
66 | BDRVQcow2State *s = bs->opaque; | ||
67 | uint64_t start, remaining; | ||
68 | @@ -XXX,XX +XXX,XX @@ again: | ||
69 | while (true) { | ||
70 | |||
71 | if (*host_offset == INV_OFFSET && cluster_offset != INV_OFFSET) { | ||
72 | - *host_offset = start_of_cluster(s, cluster_offset); | ||
73 | + *host_offset = cluster_offset; | ||
74 | } | ||
75 | |||
76 | assert(remaining >= cur_bytes); | ||
77 | @@ -XXX,XX +XXX,XX @@ again: | ||
78 | *bytes -= remaining; | ||
79 | assert(*bytes > 0); | ||
80 | assert(*host_offset != INV_OFFSET); | ||
81 | + assert(offset_into_cluster(s, *host_offset) == | ||
82 | + offset_into_cluster(s, offset)); | ||
83 | |||
84 | return 0; | ||
85 | } | ||
86 | diff --git a/block/qcow2.c b/block/qcow2.c | ||
87 | index XXXXXXX..XXXXXXX 100644 | ||
88 | --- a/block/qcow2.c | ||
89 | +++ b/block/qcow2.c | ||
90 | @@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_pwritev_part( | ||
91 | int offset_in_cluster; | ||
92 | int ret; | ||
93 | unsigned int cur_bytes; /* number of sectors in current iteration */ | ||
94 | - uint64_t cluster_offset; | ||
95 | + uint64_t host_offset; | ||
96 | QCowL2Meta *l2meta = NULL; | ||
97 | AioTaskPool *aio = NULL; | ||
98 | |||
99 | @@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_pwritev_part( | ||
100 | |||
101 | qemu_co_mutex_lock(&s->lock); | ||
102 | |||
103 | - ret = qcow2_alloc_cluster_offset(bs, offset, &cur_bytes, | ||
104 | - &cluster_offset, &l2meta); | ||
105 | + ret = qcow2_alloc_host_offset(bs, offset, &cur_bytes, | ||
106 | + &host_offset, &l2meta); | ||
107 | if (ret < 0) { | ||
108 | goto out_locked; | ||
109 | } | ||
110 | |||
111 | - assert(offset_into_cluster(s, cluster_offset) == 0); | ||
112 | - | ||
113 | - ret = qcow2_pre_write_overlap_check(bs, 0, | ||
114 | - cluster_offset + offset_in_cluster, | ||
115 | + ret = qcow2_pre_write_overlap_check(bs, 0, host_offset, | ||
116 | cur_bytes, true); | ||
117 | if (ret < 0) { | ||
118 | goto out_locked; | ||
119 | @@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_pwritev_part( | ||
120 | aio = aio_task_pool_new(QCOW2_MAX_WORKERS); | ||
121 | } | ||
122 | ret = qcow2_add_task(bs, aio, qcow2_co_pwritev_task_entry, 0, | ||
123 | - cluster_offset + offset_in_cluster, offset, | ||
124 | + host_offset, offset, | ||
125 | cur_bytes, qiov, qiov_offset, l2meta); | ||
126 | l2meta = NULL; /* l2meta is consumed by qcow2_co_pwritev_task() */ | ||
127 | if (ret < 0) { | ||
128 | @@ -XXX,XX +XXX,XX @@ static int coroutine_fn preallocate_co(BlockDriverState *bs, uint64_t offset, | ||
129 | |||
130 | while (bytes) { | ||
131 | cur_bytes = MIN(bytes, QEMU_ALIGN_DOWN(INT_MAX, s->cluster_size)); | ||
132 | - ret = qcow2_alloc_cluster_offset(bs, offset, &cur_bytes, | ||
133 | - &host_offset, &meta); | ||
134 | + ret = qcow2_alloc_host_offset(bs, offset, &cur_bytes, | ||
135 | + &host_offset, &meta); | ||
136 | if (ret < 0) { | ||
137 | error_setg_errno(errp, -ret, "Allocating clusters failed"); | ||
138 | goto out; | ||
139 | } | ||
140 | - host_offset += offset_into_cluster(s, offset); | ||
141 | |||
142 | for (m = meta; m != NULL; m = m->next) { | ||
143 | m->prealloc = true; | ||
144 | @@ -XXX,XX +XXX,XX @@ qcow2_co_copy_range_to(BlockDriverState *bs, | ||
145 | BdrvRequestFlags write_flags) | ||
146 | { | ||
147 | BDRVQcow2State *s = bs->opaque; | ||
148 | - int offset_in_cluster; | ||
149 | int ret; | ||
150 | unsigned int cur_bytes; /* number of sectors in current iteration */ | ||
151 | - uint64_t cluster_offset; | ||
152 | + uint64_t host_offset; | ||
153 | QCowL2Meta *l2meta = NULL; | ||
154 | |||
155 | assert(!bs->encrypted); | ||
156 | @@ -XXX,XX +XXX,XX @@ qcow2_co_copy_range_to(BlockDriverState *bs, | ||
157 | |||
158 | l2meta = NULL; | ||
159 | |||
160 | - offset_in_cluster = offset_into_cluster(s, dst_offset); | ||
161 | cur_bytes = MIN(bytes, INT_MAX); | ||
162 | |||
163 | /* TODO: | ||
164 | * If src->bs == dst->bs, we could simply copy by incrementing | ||
165 | * the refcnt, without copying user data. | ||
166 | * Or if src->bs == dst->bs->backing->bs, we could copy by discarding. */ | ||
167 | - ret = qcow2_alloc_cluster_offset(bs, dst_offset, &cur_bytes, | ||
168 | - &cluster_offset, &l2meta); | ||
169 | + ret = qcow2_alloc_host_offset(bs, dst_offset, &cur_bytes, | ||
170 | + &host_offset, &l2meta); | ||
171 | if (ret < 0) { | ||
172 | goto fail; | ||
173 | } | ||
174 | |||
175 | - assert(offset_into_cluster(s, cluster_offset) == 0); | ||
176 | - | ||
177 | - ret = qcow2_pre_write_overlap_check(bs, 0, | ||
178 | - cluster_offset + offset_in_cluster, cur_bytes, true); | ||
179 | + ret = qcow2_pre_write_overlap_check(bs, 0, host_offset, cur_bytes, | ||
180 | + true); | ||
181 | if (ret < 0) { | ||
182 | goto fail; | ||
183 | } | ||
184 | |||
185 | qemu_co_mutex_unlock(&s->lock); | ||
186 | - ret = bdrv_co_copy_range_to(src, src_offset, | ||
187 | - s->data_file, | ||
188 | - cluster_offset + offset_in_cluster, | ||
189 | + ret = bdrv_co_copy_range_to(src, src_offset, s->data_file, host_offset, | ||
190 | cur_bytes, read_flags, write_flags); | ||
191 | qemu_co_mutex_lock(&s->lock); | ||
192 | if (ret < 0) { | ||
193 | -- | ||
194 | 2.26.2 | ||
195 | |||
196 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | From: Stefano Garzarella <sgarzare@redhat.com> | ||
2 | 1 | ||
3 | Commit 19ae9ae014 ("block/rbd: Add support for ceph namespaces") | ||
4 | introduced namespace support for RBD, but we forgot to add the | ||
5 | new 'namespace' options to qemu_rbd_strong_runtime_opts[]. | ||
6 | |||
7 | The 'namespace' is used to identify the image, so it is a strong | ||
8 | option since it can changes the data of a BDS. | ||
9 | |||
10 | Buglink: https://bugzilla.redhat.com/show_bug.cgi?id=1821528 | ||
11 | Fixes: 19ae9ae014 ("block/rbd: Add support for ceph namespaces") | ||
12 | Cc: Florian Florensa <fflorensa@online.net> | ||
13 | Signed-off-by: Stefano Garzarella <sgarzare@redhat.com> | ||
14 | Message-Id: <20200914190553.74871-1-sgarzare@redhat.com> | ||
15 | Reviewed-by: Jason Dillaman <dillaman@redhat.com> | ||
16 | Signed-off-by: Max Reitz <mreitz@redhat.com> | ||
17 | --- | ||
18 | block/rbd.c | 1 + | ||
19 | 1 file changed, 1 insertion(+) | ||
20 | |||
21 | diff --git a/block/rbd.c b/block/rbd.c | ||
22 | index XXXXXXX..XXXXXXX 100644 | ||
23 | --- a/block/rbd.c | ||
24 | +++ b/block/rbd.c | ||
25 | @@ -XXX,XX +XXX,XX @@ static QemuOptsList qemu_rbd_create_opts = { | ||
26 | |||
27 | static const char *const qemu_rbd_strong_runtime_opts[] = { | ||
28 | "pool", | ||
29 | + "namespace", | ||
30 | "image", | ||
31 | "conf", | ||
32 | "snapshot", | ||
33 | -- | ||
34 | 2.26.2 | ||
35 | |||
36 | diff view generated by jsdifflib |