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