1
The following changes since commit 9436e082de18b2fb2ceed2e9d1beef641ae64f23:
1
The following changes since commit 1b8c45899715d292398152ba97ef755ccaf84680:
2
2
3
MAINTAINERS: clarify some of the tags (2018-11-19 11:19:23 +0000)
3
Merge remote-tracking branch 'remotes/dgilbert/tags/pull-migration-20200507a' into staging (2020-05-07 18:43:20 +0100)
4
4
5
are available in the Git repository at:
5
are available in the Git repository at:
6
6
7
git://repo.or.cz/qemu/kevin.git tags/for-upstream
7
git://repo.or.cz/qemu/kevin.git tags/for-upstream
8
8
9
for you to fetch changes up to 6d0a4a0fb5c8f10c8eb68b52cfda0082b00ae963:
9
for you to fetch changes up to 47e0b38a13935cb666f88964c3096654092f42d6:
10
10
11
iotests: Test file-posix locking and reopen (2018-11-19 14:32:04 +0100)
11
block: Drop unused .bdrv_has_zero_init_truncate (2020-05-08 13:26:35 +0200)
12
12
13
----------------------------------------------------------------
13
----------------------------------------------------------------
14
Block layer patches:
14
Block layer patches:
15
15
16
- file-posix: Fix shared permission locks after reopen
16
- qcow2: Fix preallocation on block devices
17
- block: Fix error path for failed .bdrv_reopen_prepare
17
- backup: Make sure that source and target size match
18
- qcow2: Catch invalid allocations when the image becomes too large
18
- vmdk: Fix zero cluster handling
19
- vvfat/fdc/nvme: Fix segfaults and leaks
19
- Follow-up cleanups and fixes for the truncate changes
20
- iotests: Skip more tests if required drivers are missing
20
21
21
----------------------------------------------------------------
22
----------------------------------------------------------------
22
Eric Blake (3):
23
Alberto Garcia (1):
23
qcow2: Document some maximum size constraints
24
qcow2: Avoid integer wraparound in qcow2_co_truncate()
24
qcow2: Don't allow overflow during cluster allocation
25
iotests: Add new test 220 for max compressed cluster offset
26
25
27
Kevin Wolf (1):
26
Eric Blake (9):
28
vvfat: Fix memory leak
27
gluster: Drop useless has_zero_init callback
28
file-win32: Support BDRV_REQ_ZERO_WRITE for truncate
29
nfs: Support BDRV_REQ_ZERO_WRITE for truncate
30
rbd: Support BDRV_REQ_ZERO_WRITE for truncate
31
sheepdog: Support BDRV_REQ_ZERO_WRITE for truncate
32
ssh: Support BDRV_REQ_ZERO_WRITE for truncate
33
parallels: Rework truncation logic
34
vhdx: Rework truncation logic
35
block: Drop unused .bdrv_has_zero_init_truncate
29
36
30
Li Qiang (1):
37
Kevin Wolf (11):
31
nvme: fix oob access issue(CVE-2018-16847)
38
vmdk: Rename VmdkMetaData.valid to new_allocation
39
vmdk: Fix zero cluster allocation
40
vmdk: Fix partial overwrite of zero cluster
41
vmdk: Don't update L2 table for zero write on zero cluster
42
vmdk: Flush only once in vmdk_L2update()
43
iotests: vmdk: Enable zeroed_grained=on by default
44
iotests/283: Use consistent size for source and target
45
backup: Improve error for bdrv_getlength() failure
46
backup: Make sure that source and target size match
47
iotests: Backup with different source/target size
48
iotests/055: Use cache.no-flush for vmdk target
32
49
33
Mark Cave-Ayland (1):
50
Max Reitz (1):
34
fdc: fix segfault in fdctrl_stop_transfer() when DMA is disabled
51
qcow2: Fix preallocation on block devices
35
52
36
Max Reitz (3):
53
Vladimir Sementsov-Ogievskiy (8):
37
block: Always abort reopen after prepare succeeded
54
iotests: handle tmpfs
38
file-posix: Fix shared locks on reopen commit
55
iotests/082: require bochs
39
iotests: Test file-posix locking and reopen
56
iotests/148: use skip_if_unsupported
57
iotests/041: drop self.assert_no_active_block_jobs()
58
iotests/055: refactor compressed backup to vmdk
59
iotests/055: skip vmdk target tests if vmdk is not whitelisted
60
iotests/109: mark required formats as required to support whitelisting
61
iotests/113: mark bochs as required to support whitelisting
40
62
41
docs/interop/qcow2.txt | 38 +++++++++++++++++-
63
include/block/block.h | 1 -
42
block/qcow2.h | 6 +++
64
include/block/block_int.h | 7 ---
43
block.c | 12 ++++++
65
block.c | 21 --------
44
block/file-posix.c | 2 +-
66
block/backup-top.c | 14 +++--
45
block/qcow2-refcount.c | 20 ++++++----
67
block/backup.c | 18 +++++--
46
block/vvfat.c | 6 +--
68
block/file-posix.c | 1 -
47
hw/block/fdc.c | 2 +-
69
block/file-win32.c | 4 +-
48
hw/block/nvme.c | 7 ++++
70
block/gluster.c | 14 -----
49
tests/qemu-iotests/182 | 71 ++++++++++++++++++++++++++++++++++
71
block/nfs.c | 4 +-
50
tests/qemu-iotests/182.out | 9 +++++
72
block/parallels.c | 25 +++++----
51
tests/qemu-iotests/220 | 96 ++++++++++++++++++++++++++++++++++++++++++++++
73
block/qcow2.c | 23 ++++++---
52
tests/qemu-iotests/220.out | 54 ++++++++++++++++++++++++++
74
block/qed.c | 1 -
53
tests/qemu-iotests/group | 1 +
75
block/raw-format.c | 6 ---
54
13 files changed, 310 insertions(+), 14 deletions(-)
76
block/rbd.c | 4 +-
55
create mode 100755 tests/qemu-iotests/220
77
block/sheepdog.c | 4 +-
56
create mode 100644 tests/qemu-iotests/220.out
78
block/ssh.c | 5 +-
79
block/vhdx.c | 89 ++++++++++++++++++--------------
80
block/vmdk.c | 47 ++++++++++-------
81
tests/qemu-iotests/041 | 8 ---
82
tests/qemu-iotests/055 | 120 ++++++++++++++++++++++++++++++-------------
83
tests/qemu-iotests/055.out | 4 +-
84
tests/qemu-iotests/059 | 6 +--
85
tests/qemu-iotests/082 | 1 +
86
tests/qemu-iotests/091 | 2 +-
87
tests/qemu-iotests/109 | 1 +
88
tests/qemu-iotests/113 | 4 +-
89
tests/qemu-iotests/148 | 1 +
90
tests/qemu-iotests/283 | 6 ++-
91
tests/qemu-iotests/283.out | 2 +-
92
tests/qemu-iotests/292 | 73 ++++++++++++++++++++++++++
93
tests/qemu-iotests/292.out | 24 +++++++++
94
tests/qemu-iotests/check | 3 ++
95
tests/qemu-iotests/common.rc | 37 ++++++++++++-
96
tests/qemu-iotests/group | 1 +
97
34 files changed, 386 insertions(+), 195 deletions(-)
98
create mode 100755 tests/qemu-iotests/292
99
create mode 100644 tests/qemu-iotests/292.out
57
100
101
diff view generated by jsdifflib
New patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
2
3
Some tests requires O_DIRECT, or want it by default. Introduce smarter
4
O_DIRECT handling:
5
6
- Check O_DIRECT in common.rc, if it is requested by selected
7
cache-mode.
8
9
- Support second fall-through argument in _default_cache_mode
10
11
Inspired-by: Max's 23e1d054112cec1e
12
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
13
Message-Id: <20200430124713.3067-2-vsementsov@virtuozzo.com>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
---
16
tests/qemu-iotests/091 | 2 +-
17
tests/qemu-iotests/common.rc | 37 ++++++++++++++++++++++++++++++++++--
18
2 files changed, 36 insertions(+), 3 deletions(-)
19
20
diff --git a/tests/qemu-iotests/091 b/tests/qemu-iotests/091
21
index XXXXXXX..XXXXXXX 100755
22
--- a/tests/qemu-iotests/091
23
+++ b/tests/qemu-iotests/091
24
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
25
_supported_fmt qcow2
26
_supported_proto file
27
_supported_os Linux
28
-_default_cache_mode none
29
_supported_cache_modes writethrough none writeback
30
+_default_cache_mode none writeback
31
32
size=1G
33
34
diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc
35
index XXXXXXX..XXXXXXX 100644
36
--- a/tests/qemu-iotests/common.rc
37
+++ b/tests/qemu-iotests/common.rc
38
@@ -XXX,XX +XXX,XX @@ _supported_cache_modes()
39
_notrun "not suitable for cache mode: $CACHEMODE"
40
}
41
42
+# Check whether the filesystem supports O_DIRECT
43
+_check_o_direct()
44
+{
45
+ $QEMU_IMG create -f raw "$TEST_IMG".test_o_direct 1M > /dev/null
46
+ out=$($QEMU_IO -f raw -t none -c quit "$TEST_IMG".test_o_direct 2>&1)
47
+ rm -f "$TEST_IMG".test_o_direct
48
+
49
+ [[ "$out" != *"O_DIRECT"* ]]
50
+}
51
+
52
+_require_o_direct()
53
+{
54
+ if ! _check_o_direct; then
55
+ _notrun "file system on $TEST_DIR does not support O_DIRECT"
56
+ fi
57
+}
58
+
59
+_check_cache_mode()
60
+{
61
+ if [ $CACHEMODE == "none" ] || [ $CACHEMODE == "directsync" ]; then
62
+ _require_o_direct
63
+ fi
64
+}
65
+
66
+_check_cache_mode
67
+
68
+# $1 - cache mode to use by default
69
+# $2 - (optional) cache mode to use by default if O_DIRECT is not supported
70
_default_cache_mode()
71
{
72
if $CACHEMODE_IS_DEFAULT; then
73
- CACHEMODE="$1"
74
- QEMU_IO="$QEMU_IO --cache $1"
75
+ if [ -z "$2" ] || _check_o_direct; then
76
+ CACHEMODE="$1"
77
+ else
78
+ CACHEMODE="$2"
79
+ fi
80
+ QEMU_IO="$QEMU_IO --cache $CACHEMODE"
81
+ _check_cache_mode
82
return
83
fi
84
}
85
--
86
2.25.3
87
88
diff view generated by jsdifflib
New patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
2
3
Test fails if bochs not whitelisted, so, skip it in this case.
4
5
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
6
Message-Id: <20200430124713.3067-3-vsementsov@virtuozzo.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
---
9
tests/qemu-iotests/082 | 1 +
10
1 file changed, 1 insertion(+)
11
12
diff --git a/tests/qemu-iotests/082 b/tests/qemu-iotests/082
13
index XXXXXXX..XXXXXXX 100755
14
--- a/tests/qemu-iotests/082
15
+++ b/tests/qemu-iotests/082
16
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
17
18
_supported_fmt qcow2
19
_supported_proto file nfs
20
+_require_drivers bochs
21
22
run_qemu_img()
23
{
24
--
25
2.25.3
26
27
diff view generated by jsdifflib
New patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
2
3
Skip test-case with quorum if quorum is not whitelisted.
4
5
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
6
Message-Id: <20200430124713.3067-4-vsementsov@virtuozzo.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
---
9
tests/qemu-iotests/148 | 1 +
10
1 file changed, 1 insertion(+)
11
12
diff --git a/tests/qemu-iotests/148 b/tests/qemu-iotests/148
13
index XXXXXXX..XXXXXXX 100755
14
--- a/tests/qemu-iotests/148
15
+++ b/tests/qemu-iotests/148
16
@@ -XXX,XX +XXX,XX @@ sector = "%d"
17
''' % bad_sector)
18
file.close()
19
20
+ @iotests.skip_if_unsupported(['quorum'])
21
def setUp(self):
22
driveopts = ['driver=quorum', 'vote-threshold=2']
23
driveopts.append('read-pattern=%s' % self.read_pattern)
24
--
25
2.25.3
26
27
diff view generated by jsdifflib
New patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
2
3
Drop check for no block-jobs: it's obvious that there no jobs
4
immediately after vm.launch().
5
6
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
7
Message-Id: <20200430124713.3067-5-vsementsov@virtuozzo.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
10
tests/qemu-iotests/041 | 8 --------
11
1 file changed, 8 deletions(-)
12
13
diff --git a/tests/qemu-iotests/041 b/tests/qemu-iotests/041
14
index XXXXXXX..XXXXXXX 100755
15
--- a/tests/qemu-iotests/041
16
+++ b/tests/qemu-iotests/041
17
@@ -XXX,XX +XXX,XX @@ class TestRepairQuorum(iotests.QMPTestCase):
18
pass
19
20
def test_complete(self):
21
- self.assert_no_active_block_jobs()
22
-
23
result = self.vm.qmp('drive-mirror', job_id='job0', device='quorum0',
24
sync='full', node_name="repair0", replaces="img1",
25
target=quorum_repair_img, format=iotests.imgfmt)
26
@@ -XXX,XX +XXX,XX @@ class TestRepairQuorum(iotests.QMPTestCase):
27
'target image does not match source after mirroring')
28
29
def test_cancel(self):
30
- self.assert_no_active_block_jobs()
31
-
32
result = self.vm.qmp('drive-mirror', job_id='job0', device='quorum0',
33
sync='full', node_name="repair0", replaces="img1",
34
target=quorum_repair_img, format=iotests.imgfmt)
35
@@ -XXX,XX +XXX,XX @@ class TestRepairQuorum(iotests.QMPTestCase):
36
self.assert_has_block_node(None, quorum_img3)
37
38
def test_cancel_after_ready(self):
39
- self.assert_no_active_block_jobs()
40
-
41
result = self.vm.qmp('drive-mirror', job_id='job0', device='quorum0',
42
sync='full', node_name="repair0", replaces="img1",
43
target=quorum_repair_img, format=iotests.imgfmt)
44
@@ -XXX,XX +XXX,XX @@ class TestRepairQuorum(iotests.QMPTestCase):
45
'target image does not match source after mirroring')
46
47
def test_pause(self):
48
- self.assert_no_active_block_jobs()
49
-
50
result = self.vm.qmp('drive-mirror', job_id='job0', device='quorum0',
51
sync='full', node_name="repair0", replaces="img1",
52
target=quorum_repair_img, format=iotests.imgfmt)
53
--
54
2.25.3
55
56
diff view generated by jsdifflib
New patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
2
3
Instead of looping in each test, let's better refactor vmdk target case
4
as a subclass.
5
6
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
7
Message-Id: <20200430124713.3067-6-vsementsov@virtuozzo.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
10
tests/qemu-iotests/055 | 70 ++++++++++++++++++++------------------
11
tests/qemu-iotests/055.out | 4 +--
12
2 files changed, 39 insertions(+), 35 deletions(-)
13
14
diff --git a/tests/qemu-iotests/055 b/tests/qemu-iotests/055
15
index XXXXXXX..XXXXXXX 100755
16
--- a/tests/qemu-iotests/055
17
+++ b/tests/qemu-iotests/055
18
@@ -XXX,XX +XXX,XX @@ class TestSingleTransaction(iotests.QMPTestCase):
19
self.assert_no_active_block_jobs()
20
21
22
-class TestDriveCompression(iotests.QMPTestCase):
23
+class TestCompressedToQcow2(iotests.QMPTestCase):
24
image_len = 64 * 1024 * 1024 # MB
25
- fmt_supports_compression = [{'type': 'qcow2', 'args': ()},
26
- {'type': 'vmdk', 'args': ('-o', 'subformat=streamOptimized')}]
27
+ target_fmt = {'type': 'qcow2', 'args': ()}
28
29
def tearDown(self):
30
self.vm.shutdown()
31
@@ -XXX,XX +XXX,XX @@ class TestDriveCompression(iotests.QMPTestCase):
32
except OSError:
33
pass
34
35
- def do_prepare_drives(self, fmt, args, attach_target):
36
+ def do_prepare_drives(self, attach_target):
37
self.vm = iotests.VM().add_drive('blkdebug::' + test_img)
38
39
- qemu_img('create', '-f', fmt, blockdev_target_img,
40
- str(TestDriveCompression.image_len), *args)
41
+ qemu_img('create', '-f', self.target_fmt['type'], blockdev_target_img,
42
+ str(self.image_len), *self.target_fmt['args'])
43
if attach_target:
44
self.vm.add_drive(blockdev_target_img,
45
- img_format=fmt, interface="none")
46
+ img_format=self.target_fmt['type'],
47
+ interface="none")
48
49
self.vm.launch()
50
51
- def do_test_compress_complete(self, cmd, format, attach_target, **args):
52
- self.do_prepare_drives(format['type'], format['args'], attach_target)
53
+ def do_test_compress_complete(self, cmd, attach_target, **args):
54
+ self.do_prepare_drives(attach_target)
55
56
self.assert_no_active_block_jobs()
57
58
@@ -XXX,XX +XXX,XX @@ class TestDriveCompression(iotests.QMPTestCase):
59
60
self.vm.shutdown()
61
self.assertTrue(iotests.compare_images(test_img, blockdev_target_img,
62
- iotests.imgfmt, format['type']),
63
+ iotests.imgfmt,
64
+ self.target_fmt['type']),
65
'target image does not match source after backup')
66
67
def test_complete_compress_drive_backup(self):
68
- for format in TestDriveCompression.fmt_supports_compression:
69
- self.do_test_compress_complete('drive-backup', format, False,
70
- target=blockdev_target_img, mode='existing')
71
+ self.do_test_compress_complete('drive-backup', False,
72
+ target=blockdev_target_img,
73
+ mode='existing')
74
75
def test_complete_compress_blockdev_backup(self):
76
- for format in TestDriveCompression.fmt_supports_compression:
77
- self.do_test_compress_complete('blockdev-backup', format, True,
78
- target='drive1')
79
+ self.do_test_compress_complete('blockdev-backup',
80
+ True, target='drive1')
81
82
- def do_test_compress_cancel(self, cmd, format, attach_target, **args):
83
- self.do_prepare_drives(format['type'], format['args'], attach_target)
84
+ def do_test_compress_cancel(self, cmd, attach_target, **args):
85
+ self.do_prepare_drives(attach_target)
86
87
self.assert_no_active_block_jobs()
88
89
@@ -XXX,XX +XXX,XX @@ class TestDriveCompression(iotests.QMPTestCase):
90
self.vm.shutdown()
91
92
def test_compress_cancel_drive_backup(self):
93
- for format in TestDriveCompression.fmt_supports_compression:
94
- self.do_test_compress_cancel('drive-backup', format, False,
95
- target=blockdev_target_img, mode='existing')
96
+ self.do_test_compress_cancel('drive-backup', False,
97
+ target=blockdev_target_img,
98
+ mode='existing')
99
100
def test_compress_cancel_blockdev_backup(self):
101
- for format in TestDriveCompression.fmt_supports_compression:
102
- self.do_test_compress_cancel('blockdev-backup', format, True,
103
- target='drive1')
104
+ self.do_test_compress_cancel('blockdev-backup', True,
105
+ target='drive1')
106
107
- def do_test_compress_pause(self, cmd, format, attach_target, **args):
108
- self.do_prepare_drives(format['type'], format['args'], attach_target)
109
+ def do_test_compress_pause(self, cmd, attach_target, **args):
110
+ self.do_prepare_drives(attach_target)
111
112
self.assert_no_active_block_jobs()
113
114
@@ -XXX,XX +XXX,XX @@ class TestDriveCompression(iotests.QMPTestCase):
115
116
self.vm.shutdown()
117
self.assertTrue(iotests.compare_images(test_img, blockdev_target_img,
118
- iotests.imgfmt, format['type']),
119
+ iotests.imgfmt,
120
+ self.target_fmt['type']),
121
'target image does not match source after backup')
122
123
def test_compress_pause_drive_backup(self):
124
- for format in TestDriveCompression.fmt_supports_compression:
125
- self.do_test_compress_pause('drive-backup', format, False,
126
- target=blockdev_target_img, mode='existing')
127
+ self.do_test_compress_pause('drive-backup', False,
128
+ target=blockdev_target_img,
129
+ mode='existing')
130
131
def test_compress_pause_blockdev_backup(self):
132
- for format in TestDriveCompression.fmt_supports_compression:
133
- self.do_test_compress_pause('blockdev-backup', format, True,
134
- target='drive1')
135
+ self.do_test_compress_pause('blockdev-backup', True,
136
+ target='drive1')
137
+
138
+
139
+class TestCompressedToVmdk(TestCompressedToQcow2):
140
+ target_fmt = {'type': 'vmdk', 'args': ('-o', 'subformat=streamOptimized')}
141
+
142
143
if __name__ == '__main__':
144
iotests.main(supported_fmts=['raw', 'qcow2'],
145
diff --git a/tests/qemu-iotests/055.out b/tests/qemu-iotests/055.out
146
index XXXXXXX..XXXXXXX 100644
147
--- a/tests/qemu-iotests/055.out
148
+++ b/tests/qemu-iotests/055.out
149
@@ -XXX,XX +XXX,XX @@
150
-..............................
151
+....................................
152
----------------------------------------------------------------------
153
-Ran 30 tests
154
+Ran 36 tests
155
156
OK
157
--
158
2.25.3
159
160
diff view generated by jsdifflib
New patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
2
3
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
4
Message-Id: <20200430124713.3067-7-vsementsov@virtuozzo.com>
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
---
7
tests/qemu-iotests/055 | 4 ++++
8
1 file changed, 4 insertions(+)
9
10
diff --git a/tests/qemu-iotests/055 b/tests/qemu-iotests/055
11
index XXXXXXX..XXXXXXX 100755
12
--- a/tests/qemu-iotests/055
13
+++ b/tests/qemu-iotests/055
14
@@ -XXX,XX +XXX,XX @@ class TestCompressedToQcow2(iotests.QMPTestCase):
15
class TestCompressedToVmdk(TestCompressedToQcow2):
16
target_fmt = {'type': 'vmdk', 'args': ('-o', 'subformat=streamOptimized')}
17
18
+ @iotests.skip_if_unsupported(['vmdk'])
19
+ def setUp(self):
20
+ pass
21
+
22
23
if __name__ == '__main__':
24
iotests.main(supported_fmts=['raw', 'qcow2'],
25
--
26
2.25.3
27
28
diff view generated by jsdifflib
New patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
2
3
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
4
Message-Id: <20200430124713.3067-8-vsementsov@virtuozzo.com>
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
---
7
tests/qemu-iotests/109 | 1 +
8
1 file changed, 1 insertion(+)
9
10
diff --git a/tests/qemu-iotests/109 b/tests/qemu-iotests/109
11
index XXXXXXX..XXXXXXX 100755
12
--- a/tests/qemu-iotests/109
13
+++ b/tests/qemu-iotests/109
14
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
15
_supported_fmt raw
16
_supported_proto file
17
_supported_os Linux
18
+_require_drivers qcow qcow2 qed vdi vmdk vpc
19
20
qemu_comm_method=qmp
21
22
--
23
2.25.3
24
25
diff view generated by jsdifflib
New patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
2
3
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
4
Message-Id: <20200430124713.3067-9-vsementsov@virtuozzo.com>
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
---
7
tests/qemu-iotests/113 | 4 ++--
8
1 file changed, 2 insertions(+), 2 deletions(-)
9
10
diff --git a/tests/qemu-iotests/113 b/tests/qemu-iotests/113
11
index XXXXXXX..XXXXXXX 100755
12
--- a/tests/qemu-iotests/113
13
+++ b/tests/qemu-iotests/113
14
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
15
. ./common.rc
16
. ./common.filter
17
18
-# Some of these test cases use bochs, but others do use raw, so this
19
-# is only half a lie.
20
+# Some of these test cases use bochs, but others do use raw
21
+_require_drivers bochs
22
_supported_fmt raw
23
_supported_proto file
24
_supported_os Linux
25
--
26
2.25.3
27
28
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
1
From: Alberto Garcia <berto@igalia.com>
2
2
3
If you have a capable file system (tmpfs is good, ext4 not so much;
3
After commit f01643fb8b47e8a70c04bbf45e0f12a9e5bc54de when an image is
4
run ./check with TEST_DIR pointing to a good location so as not
4
extended and BDRV_REQ_ZERO_WRITE is set then the new clusters are
5
to skip the test), it's actually possible to create a qcow2 file
5
zeroized.
6
that expands to a sparse 512T image with just over 38M of content.
7
The test is not the world's fastest (qemu crawling through 256M
8
bits of refcount table to find the next cluster to allocate takes
9
several seconds, as does qemu-img check reporting millions of
10
leaked clusters); but it DOES catch the problem that the previous
11
patch just fixed where writing a compressed cluster to a full
12
image ended up overwriting the wrong cluster.
13
6
14
Suggested-by: Max Reitz <mreitz@redhat.com>
7
The code however does not detect correctly situations when the old and
15
Signed-off-by: Eric Blake <eblake@redhat.com>
8
the new end of the image are within the same cluster. The problem can
16
Reviewed-by: Alberto Garcia <berto@igalia.com>
9
be reproduced with these steps:
10
11
qemu-img create -f qcow2 backing.qcow2 1M
12
qemu-img create -f qcow2 -F qcow2 -b backing.qcow2 top.qcow2
13
qemu-img resize --shrink top.qcow2 520k
14
qemu-img resize top.qcow2 567k
15
16
In the last step offset - zero_start causes an integer wraparound.
17
18
Signed-off-by: Alberto Garcia <berto@igalia.com>
19
Message-Id: <20200504155217.10325-1-berto@igalia.com>
20
Reviewed-by: Eric Blake <eblake@redhat.com>
17
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
21
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
18
---
22
---
19
tests/qemu-iotests/220 | 96 ++++++++++++++++++++++++++++++++++++++
23
block/qcow2.c | 12 ++++---
20
tests/qemu-iotests/220.out | 54 +++++++++++++++++++++
24
tests/qemu-iotests/292 | 73 ++++++++++++++++++++++++++++++++++++++
25
tests/qemu-iotests/292.out | 24 +++++++++++++
21
tests/qemu-iotests/group | 1 +
26
tests/qemu-iotests/group | 1 +
22
3 files changed, 151 insertions(+)
27
4 files changed, 105 insertions(+), 5 deletions(-)
23
create mode 100755 tests/qemu-iotests/220
28
create mode 100755 tests/qemu-iotests/292
24
create mode 100644 tests/qemu-iotests/220.out
29
create mode 100644 tests/qemu-iotests/292.out
25
30
26
diff --git a/tests/qemu-iotests/220 b/tests/qemu-iotests/220
31
diff --git a/block/qcow2.c b/block/qcow2.c
32
index XXXXXXX..XXXXXXX 100644
33
--- a/block/qcow2.c
34
+++ b/block/qcow2.c
35
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
36
* requires a cluster-aligned start. The end may be unaligned if it is
37
* at the end of the image (which it is here).
38
*/
39
- ret = qcow2_cluster_zeroize(bs, zero_start, offset - zero_start, 0);
40
- if (ret < 0) {
41
- error_setg_errno(errp, -ret, "Failed to zero out new clusters");
42
- goto fail;
43
+ if (offset > zero_start) {
44
+ ret = qcow2_cluster_zeroize(bs, zero_start, offset - zero_start, 0);
45
+ if (ret < 0) {
46
+ error_setg_errno(errp, -ret, "Failed to zero out new clusters");
47
+ goto fail;
48
+ }
49
}
50
51
/* Write explicit zeros for the unaligned head */
52
if (zero_start > old_length) {
53
- uint64_t len = zero_start - old_length;
54
+ uint64_t len = MIN(zero_start, offset) - old_length;
55
uint8_t *buf = qemu_blockalign0(bs, len);
56
QEMUIOVector qiov;
57
qemu_iovec_init_buf(&qiov, buf, len);
58
diff --git a/tests/qemu-iotests/292 b/tests/qemu-iotests/292
27
new file mode 100755
59
new file mode 100755
28
index XXXXXXX..XXXXXXX
60
index XXXXXXX..XXXXXXX
29
--- /dev/null
61
--- /dev/null
30
+++ b/tests/qemu-iotests/220
62
+++ b/tests/qemu-iotests/292
31
@@ -XXX,XX +XXX,XX @@
63
@@ -XXX,XX +XXX,XX @@
32
+#!/bin/bash
64
+#!/usr/bin/env bash
33
+#
65
+#
34
+# max limits on compression in huge qcow2 files
66
+# Test resizing a qcow2 image with a backing file
35
+#
67
+#
36
+# Copyright (C) 2018 Red Hat, Inc.
68
+# Copyright (C) 2020 Igalia, S.L.
69
+# Author: Alberto Garcia <berto@igalia.com>
37
+#
70
+#
38
+# This program is free software; you can redistribute it and/or modify
71
+# This program is free software; you can redistribute it and/or modify
39
+# it under the terms of the GNU General Public License as published by
72
+# it under the terms of the GNU General Public License as published by
40
+# the Free Software Foundation; either version 2 of the License, or
73
+# the Free Software Foundation; either version 2 of the License, or
41
+# (at your option) any later version.
74
+# (at your option) any later version.
...
...
47
+#
80
+#
48
+# You should have received a copy of the GNU General Public License
81
+# You should have received a copy of the GNU General Public License
49
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
82
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
50
+#
83
+#
51
+
84
+
52
+seq=$(basename $0)
85
+# creator
86
+owner=berto@igalia.com
87
+
88
+seq=`basename $0`
53
+echo "QA output created by $seq"
89
+echo "QA output created by $seq"
54
+
90
+
55
+status=1 # failure is the default!
91
+status=1 # failure is the default!
56
+
92
+
57
+_cleanup()
93
+_cleanup()
...
...
61
+trap "_cleanup; exit \$status" 0 1 2 3 15
97
+trap "_cleanup; exit \$status" 0 1 2 3 15
62
+
98
+
63
+# get standard environment, filters and checks
99
+# get standard environment, filters and checks
64
+. ./common.rc
100
+. ./common.rc
65
+. ./common.filter
101
+. ./common.filter
66
+. ./common.pattern
67
+
102
+
68
+_supported_fmt qcow2
103
+_supported_fmt qcow2
69
+_supported_proto file
104
+_supported_proto file
70
+_supported_os Linux
105
+_supported_os Linux
71
+
106
+
72
+echo "== Creating huge file =="
107
+echo '### Create the backing image'
108
+BACKING_IMG="$TEST_IMG.base"
109
+TEST_IMG="$BACKING_IMG" _make_test_img 1M
73
+
110
+
74
+# Sanity check: We require a file system that permits the creation
111
+echo '### Fill the backing image with data (0x11)'
75
+# of a HUGE (but very sparse) file. tmpfs works, ext4 does not.
112
+$QEMU_IO -c 'write -P 0x11 0 1M' "$BACKING_IMG" | _filter_qemu_io
76
+if ! truncate --size=513T "$TEST_IMG"; then
77
+ _notrun "file system on $TEST_DIR does not support large enough files"
78
+fi
79
+rm "$TEST_IMG"
80
+IMGOPTS='cluster_size=2M,refcount_bits=1' _make_test_img 513T
81
+
113
+
82
+echo "== Populating refcounts =="
114
+echo '### Create the top image'
83
+# We want an image with 256M refcounts * 2M clusters = 512T referenced.
115
+_make_test_img -F "$IMGFMT" -b "$BACKING_IMG"
84
+# Each 2M cluster holds 16M refcounts; the refcount table initially uses
85
+# 1 refblock, so we need to add 15 more. The refcount table lives at 2M,
86
+# first refblock at 4M, L2 at 6M, so our remaining additions start at 8M.
87
+# Then, for each refblock, mark it as fully populated.
88
+to_hex() {
89
+ printf %016x\\n $1 | sed 's/\(..\)/\\x\1/g'
90
+}
91
+truncate --size=38m "$TEST_IMG"
92
+entry=$((0x200000))
93
+$QEMU_IO_PROG -f raw -c "w -P 0xff 4m 2m" "$TEST_IMG" | _filter_qemu_io
94
+for i in {1..15}; do
95
+ offs=$((0x600000 + i*0x200000))
96
+ poke_file "$TEST_IMG" $((i*8 + entry)) $(to_hex $offs)
97
+ $QEMU_IO_PROG -f raw -c "w -P 0xff $offs 2m" "$TEST_IMG" | _filter_qemu_io
98
+done
99
+
116
+
100
+echo "== Checking file before =="
117
+echo '### Fill the top image with data (0x22)'
101
+# FIXME: 'qemu-img check' doesn't diagnose refcounts beyond the end of
118
+$QEMU_IO -c 'write -P 0x22 0 1M' "$TEST_IMG" | _filter_qemu_io
102
+# the file as leaked clusters
103
+_check_test_img 2>&1 | sed '/^Leaked cluster/d'
104
+stat -c 'image size %s' "$TEST_IMG"
105
+
119
+
106
+echo "== Trying to write compressed cluster =="
120
+# Both offsets are part of the same cluster.
107
+# Given our file size, the next available cluster at 512T lies beyond the
121
+echo '### Shrink the image to 520k'
108
+# maximum offset that a compressed 2M cluster can reside in
122
+$QEMU_IMG resize --shrink "$TEST_IMG" 520k
109
+$QEMU_IO_PROG -c 'w -c 0 2m' "$TEST_IMG" | _filter_qemu_io
123
+echo '### Grow the image to 567k'
110
+# The attempt failed, but ended up allocating a new refblock
124
+$QEMU_IMG resize "$TEST_IMG" 567k
111
+stat -c 'image size %s' "$TEST_IMG"
112
+
125
+
113
+echo "== Writing normal cluster =="
126
+echo '### Check that the tail of the image reads as zeroes'
114
+# The failed write should not corrupt the image, so a normal write succeeds
127
+$QEMU_IO -c 'read -P 0x22 0 520k' "$TEST_IMG" | _filter_qemu_io
115
+$QEMU_IO_PROG -c 'w 0 2m' "$TEST_IMG" | _filter_qemu_io
128
+$QEMU_IO -c 'read -P 0x00 520k 47k' "$TEST_IMG" | _filter_qemu_io
116
+
129
+
117
+echo "== Checking file after =="
130
+echo '### Show output of qemu-img map'
118
+# qemu-img now sees the millions of leaked clusters, thanks to the allocations
131
+$QEMU_IMG map "$TEST_IMG" | _filter_testdir
119
+# at 512T. Undo many of our faked references to speed up the check.
120
+$QEMU_IO_PROG -f raw -c "w -z 5m 1m" -c "w -z 8m 30m" "$TEST_IMG" |
121
+ _filter_qemu_io
122
+_check_test_img 2>&1 | sed '/^Leaked cluster/d'
123
+
132
+
124
+# success, all done
133
+# success, all done
125
+echo "*** done"
134
+echo "*** done"
126
+rm -f $seq.full
135
+rm -f $seq.full
127
+status=0
136
+status=0
128
diff --git a/tests/qemu-iotests/220.out b/tests/qemu-iotests/220.out
137
diff --git a/tests/qemu-iotests/292.out b/tests/qemu-iotests/292.out
129
new file mode 100644
138
new file mode 100644
130
index XXXXXXX..XXXXXXX
139
index XXXXXXX..XXXXXXX
131
--- /dev/null
140
--- /dev/null
132
+++ b/tests/qemu-iotests/220.out
141
+++ b/tests/qemu-iotests/292.out
133
@@ -XXX,XX +XXX,XX @@
142
@@ -XXX,XX +XXX,XX @@
134
+QA output created by 220
143
+QA output created by 292
135
+== Creating huge file ==
144
+### Create the backing image
136
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=564049465049088
145
+Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=1048576
137
+== Populating refcounts ==
146
+### Fill the backing image with data (0x11)
138
+wrote 2097152/2097152 bytes at offset 4194304
147
+wrote 1048576/1048576 bytes at offset 0
139
+2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
140
+wrote 2097152/2097152 bytes at offset 8388608
141
+2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
142
+wrote 2097152/2097152 bytes at offset 10485760
143
+2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
144
+wrote 2097152/2097152 bytes at offset 12582912
145
+2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
146
+wrote 2097152/2097152 bytes at offset 14680064
147
+2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
148
+wrote 2097152/2097152 bytes at offset 16777216
149
+2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
150
+wrote 2097152/2097152 bytes at offset 18874368
151
+2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
152
+wrote 2097152/2097152 bytes at offset 20971520
153
+2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
154
+wrote 2097152/2097152 bytes at offset 23068672
155
+2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
156
+wrote 2097152/2097152 bytes at offset 25165824
157
+2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
158
+wrote 2097152/2097152 bytes at offset 27262976
159
+2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
160
+wrote 2097152/2097152 bytes at offset 29360128
161
+2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
162
+wrote 2097152/2097152 bytes at offset 31457280
163
+2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
164
+wrote 2097152/2097152 bytes at offset 33554432
165
+2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
166
+wrote 2097152/2097152 bytes at offset 35651584
167
+2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
168
+wrote 2097152/2097152 bytes at offset 37748736
169
+2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
170
+== Checking file before ==
171
+No errors were found on the image.
172
+image size 39845888
173
+== Trying to write compressed cluster ==
174
+write failed: Input/output error
175
+image size 562949957615616
176
+== Writing normal cluster ==
177
+wrote 2097152/2097152 bytes at offset 0
178
+2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
179
+== Checking file after ==
180
+wrote 1048576/1048576 bytes at offset 5242880
181
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
148
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
182
+wrote 31457280/31457280 bytes at offset 8388608
149
+### Create the top image
183
+30 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
150
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT
184
+
151
+### Fill the top image with data (0x22)
185
+8388589 leaked clusters were found on the image.
152
+wrote 1048576/1048576 bytes at offset 0
186
+This means waste of disk space, but no harm to data.
153
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
154
+### Shrink the image to 520k
155
+Image resized.
156
+### Grow the image to 567k
157
+Image resized.
158
+### Check that the tail of the image reads as zeroes
159
+read 532480/532480 bytes at offset 0
160
+520 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
161
+read 48128/48128 bytes at offset 532480
162
+47 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
163
+### Show output of qemu-img map
164
+Offset Length Mapped to File
165
+0 0x8dc00 0x50000 TEST_DIR/t.qcow2
187
+*** done
166
+*** done
188
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
167
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
189
index XXXXXXX..XXXXXXX 100644
168
index XXXXXXX..XXXXXXX 100644
190
--- a/tests/qemu-iotests/group
169
--- a/tests/qemu-iotests/group
191
+++ b/tests/qemu-iotests/group
170
+++ b/tests/qemu-iotests/group
192
@@ -XXX,XX +XXX,XX @@
171
@@ -XXX,XX +XXX,XX @@
193
217 rw auto quick
172
288 quick
194
218 rw auto quick
173
289 rw quick
195
219 rw auto
174
290 rw auto quick
196
+220 rw auto
175
+292 rw auto quick
197
221 rw auto quick
198
222 rw auto quick
199
223 rw auto quick
200
--
176
--
201
2.19.1
177
2.25.3
202
178
203
179
diff view generated by jsdifflib
New patch
1
m_data is used for zero clusters even though valid == 0. It really only
2
means that a new cluster was allocated in the image file. Rename it to
3
reflect this.
1
4
5
While at it, change it from int to bool, too.
6
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
Message-Id: <20200430133007.170335-2-kwolf@redhat.com>
9
Reviewed-by: Eric Blake <eblake@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
---
12
block/vmdk.c | 8 ++++----
13
1 file changed, 4 insertions(+), 4 deletions(-)
14
15
diff --git a/block/vmdk.c b/block/vmdk.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/block/vmdk.c
18
+++ b/block/vmdk.c
19
@@ -XXX,XX +XXX,XX @@ typedef struct VmdkMetaData {
20
unsigned int l1_index;
21
unsigned int l2_index;
22
unsigned int l2_offset;
23
- int valid;
24
+ bool new_allocation;
25
uint32_t *l2_cache_entry;
26
} VmdkMetaData;
27
28
@@ -XXX,XX +XXX,XX @@ static int get_cluster_offset(BlockDriverState *bs,
29
unsigned int l2_size_bytes = extent->l2_size * extent->entry_size;
30
31
if (m_data) {
32
- m_data->valid = 0;
33
+ m_data->new_allocation = false;
34
}
35
if (extent->flat) {
36
*cluster_offset = extent->flat_start_offset;
37
@@ -XXX,XX +XXX,XX @@ static int get_cluster_offset(BlockDriverState *bs,
38
return ret;
39
}
40
if (m_data) {
41
- m_data->valid = 1;
42
+ m_data->new_allocation = true;
43
m_data->l1_index = l1_index;
44
m_data->l2_index = l2_index;
45
m_data->l2_offset = l2_offset;
46
@@ -XXX,XX +XXX,XX @@ static int vmdk_pwritev(BlockDriverState *bs, uint64_t offset,
47
if (ret) {
48
return ret;
49
}
50
- if (m_data.valid) {
51
+ if (m_data.new_allocation) {
52
/* update L2 tables */
53
if (vmdk_L2update(extent, &m_data,
54
cluster_offset >> BDRV_SECTOR_BITS)
55
--
56
2.25.3
57
58
diff view generated by jsdifflib
New patch
1
m_data must contain valid data even for zero clusters when no cluster
2
was allocated in the image file. Without this, zero writes segfault with
3
images that have zeroed_grain=on.
1
4
5
For zero writes, we don't want to allocate a cluster in the image file
6
even in compressed files.
7
8
Fixes: 524089bce43fd1cd3daaca979872451efa2cf7c6
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
Message-Id: <20200430133007.170335-3-kwolf@redhat.com>
11
Reviewed-by: Eric Blake <eblake@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
---
14
block/vmdk.c | 12 +++++++-----
15
1 file changed, 7 insertions(+), 5 deletions(-)
16
17
diff --git a/block/vmdk.c b/block/vmdk.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/block/vmdk.c
20
+++ b/block/vmdk.c
21
@@ -XXX,XX +XXX,XX @@ static int get_cluster_offset(BlockDriverState *bs,
22
extent->l2_cache_counts[min_index] = 1;
23
found:
24
l2_index = ((offset >> 9) / extent->cluster_sectors) % extent->l2_size;
25
+ if (m_data) {
26
+ m_data->l1_index = l1_index;
27
+ m_data->l2_index = l2_index;
28
+ m_data->l2_offset = l2_offset;
29
+ m_data->l2_cache_entry = ((uint32_t *)l2_table) + l2_index;
30
+ }
31
32
if (extent->sesparse) {
33
cluster_sector = le64_to_cpu(((uint64_t *)l2_table)[l2_index]);
34
@@ -XXX,XX +XXX,XX @@ static int get_cluster_offset(BlockDriverState *bs,
35
}
36
if (m_data) {
37
m_data->new_allocation = true;
38
- m_data->l1_index = l1_index;
39
- m_data->l2_index = l2_index;
40
- m_data->l2_offset = l2_offset;
41
- m_data->l2_cache_entry = ((uint32_t *)l2_table) + l2_index;
42
}
43
}
44
*cluster_offset = cluster_sector << BDRV_SECTOR_BITS;
45
@@ -XXX,XX +XXX,XX @@ static int vmdk_pwritev(BlockDriverState *bs, uint64_t offset,
46
error_report("Could not write to allocated cluster"
47
" for streamOptimized");
48
return -EIO;
49
- } else {
50
+ } else if (!zeroed) {
51
/* allocate */
52
ret = get_cluster_offset(bs, extent, &m_data, offset,
53
true, &cluster_offset, 0, 0);
54
--
55
2.25.3
56
57
diff view generated by jsdifflib
New patch
1
When overwriting a zero cluster, we must not perform copy-on-write from
2
the backing file, but from a zeroed buffer.
1
3
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
Message-Id: <20200430133007.170335-4-kwolf@redhat.com>
6
Reviewed-by: Eric Blake <eblake@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
---
9
block/vmdk.c | 18 ++++++++++++------
10
1 file changed, 12 insertions(+), 6 deletions(-)
11
12
diff --git a/block/vmdk.c b/block/vmdk.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/block/vmdk.c
15
+++ b/block/vmdk.c
16
@@ -XXX,XX +XXX,XX @@ static void vmdk_refresh_limits(BlockDriverState *bs, Error **errp)
17
* get_whole_cluster
18
*
19
* Copy backing file's cluster that covers @sector_num, otherwise write zero,
20
- * to the cluster at @cluster_sector_num.
21
+ * to the cluster at @cluster_sector_num. If @zeroed is true, we're overwriting
22
+ * a zeroed cluster in the current layer and must not copy data from the
23
+ * backing file.
24
*
25
* If @skip_start_sector < @skip_end_sector, the relative range
26
* [@skip_start_sector, @skip_end_sector) is not copied or written, and leave
27
@@ -XXX,XX +XXX,XX @@ static int get_whole_cluster(BlockDriverState *bs,
28
uint64_t cluster_offset,
29
uint64_t offset,
30
uint64_t skip_start_bytes,
31
- uint64_t skip_end_bytes)
32
+ uint64_t skip_end_bytes,
33
+ bool zeroed)
34
{
35
int ret = VMDK_OK;
36
int64_t cluster_bytes;
37
uint8_t *whole_grain;
38
+ bool copy_from_backing;
39
40
/* For COW, align request sector_num to cluster start */
41
cluster_bytes = extent->cluster_sectors << BDRV_SECTOR_BITS;
42
offset = QEMU_ALIGN_DOWN(offset, cluster_bytes);
43
whole_grain = qemu_blockalign(bs, cluster_bytes);
44
+ copy_from_backing = bs->backing && !zeroed;
45
46
- if (!bs->backing) {
47
+ if (!copy_from_backing) {
48
memset(whole_grain, 0, skip_start_bytes);
49
memset(whole_grain + skip_end_bytes, 0, cluster_bytes - skip_end_bytes);
50
}
51
@@ -XXX,XX +XXX,XX @@ static int get_whole_cluster(BlockDriverState *bs,
52
53
/* Read backing data before skip range */
54
if (skip_start_bytes > 0) {
55
- if (bs->backing) {
56
+ if (copy_from_backing) {
57
/* qcow2 emits this on bs->file instead of bs->backing */
58
BLKDBG_EVENT(extent->file, BLKDBG_COW_READ);
59
ret = bdrv_pread(bs->backing, offset, whole_grain,
60
@@ -XXX,XX +XXX,XX @@ static int get_whole_cluster(BlockDriverState *bs,
61
}
62
/* Read backing data after skip range */
63
if (skip_end_bytes < cluster_bytes) {
64
- if (bs->backing) {
65
+ if (copy_from_backing) {
66
/* qcow2 emits this on bs->file instead of bs->backing */
67
BLKDBG_EVENT(extent->file, BLKDBG_COW_READ);
68
ret = bdrv_pread(bs->backing, offset + skip_end_bytes,
69
@@ -XXX,XX +XXX,XX @@ static int get_cluster_offset(BlockDriverState *bs,
70
* or inappropriate VM shutdown.
71
*/
72
ret = get_whole_cluster(bs, extent, cluster_sector * BDRV_SECTOR_SIZE,
73
- offset, skip_start_bytes, skip_end_bytes);
74
+ offset, skip_start_bytes, skip_end_bytes,
75
+ zeroed);
76
if (ret) {
77
return ret;
78
}
79
--
80
2.25.3
81
82
diff view generated by jsdifflib
New patch
1
If a cluster is already zeroed, we don't have to call vmdk_L2update(),
2
which is rather slow because it flushes the image file.
1
3
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
Message-Id: <20200430133007.170335-5-kwolf@redhat.com>
6
Reviewed-by: Eric Blake <eblake@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
---
9
block/vmdk.c | 2 +-
10
1 file changed, 1 insertion(+), 1 deletion(-)
11
12
diff --git a/block/vmdk.c b/block/vmdk.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/block/vmdk.c
15
+++ b/block/vmdk.c
16
@@ -XXX,XX +XXX,XX @@ static int vmdk_pwritev(BlockDriverState *bs, uint64_t offset,
17
offset_in_cluster == 0 &&
18
n_bytes >= extent->cluster_sectors * BDRV_SECTOR_SIZE) {
19
n_bytes = extent->cluster_sectors * BDRV_SECTOR_SIZE;
20
- if (!zero_dry_run) {
21
+ if (!zero_dry_run && ret != VMDK_ZEROED) {
22
/* update L2 tables */
23
if (vmdk_L2update(extent, &m_data, VMDK_GTE_ZEROED)
24
!= VMDK_OK) {
25
--
26
2.25.3
27
28
diff view generated by jsdifflib
1
From: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
1
If we have a backup L2 table, we currently flush once after writing to
2
the active L2 table and again after writing to the backup table. A
3
single flush is enough and makes things a little less slow.
2
4
3
Commit c8a35f1cf0f "fdc: use IsaDma interface instead of global DMA_*
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
functions" accidentally introduced a segfault in fdctrl_stop_transfer() for
6
Message-Id: <20200430133007.170335-6-kwolf@redhat.com>
5
non-DMA transfers.
7
Reviewed-by: Eric Blake <eblake@redhat.com>
6
7
If fdctrl->dma_chann has not been configured then the fdctrl->dma interface
8
reference isn't initialised during isabus_fdc_realize(). Unfortunately
9
fdctrl_stop_transfer() unconditionally references the DMA interface when
10
finishing the transfer causing a NULL pointer dereference.
11
12
Fix the issue by adding a check in fdctrl_stop_transfer() so that the DMA
13
interface reference and release method is only invoked if fdctrl->dma_chann
14
has been set.
15
16
(This issue was discovered by Martin testing a recent change in the NetBSD
17
installer under qemu-system-sparc)
18
19
Cc: qemu-stable@nongnu.org
20
Reported-by: Martin Husemann <martin@duskware.de>
21
Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
22
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
23
Reviewed-by: Hervé Poussineau <hpoussin@reactos.org>
24
Reviewed-by: John Snow <jsnow@redhat.com>
25
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
26
---
9
---
27
hw/block/fdc.c | 2 +-
10
block/vmdk.c | 7 +++++--
28
1 file changed, 1 insertion(+), 1 deletion(-)
11
1 file changed, 5 insertions(+), 2 deletions(-)
29
12
30
diff --git a/hw/block/fdc.c b/hw/block/fdc.c
13
diff --git a/block/vmdk.c b/block/vmdk.c
31
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
32
--- a/hw/block/fdc.c
15
--- a/block/vmdk.c
33
+++ b/hw/block/fdc.c
16
+++ b/block/vmdk.c
34
@@ -XXX,XX +XXX,XX @@ static void fdctrl_stop_transfer(FDCtrl *fdctrl, uint8_t status0,
17
@@ -XXX,XX +XXX,XX @@ static int vmdk_L2update(VmdkExtent *extent, VmdkMetaData *m_data,
35
fdctrl->fifo[5] = cur_drv->sect;
18
offset = cpu_to_le32(offset);
36
fdctrl->fifo[6] = FD_SECTOR_SC;
19
/* update L2 table */
37
fdctrl->data_dir = FD_DIR_READ;
20
BLKDBG_EVENT(extent->file, BLKDBG_L2_UPDATE);
38
- if (!(fdctrl->msr & FD_MSR_NONDMA)) {
21
- if (bdrv_pwrite_sync(extent->file,
39
+ if (fdctrl->dma_chann != -1 && !(fdctrl->msr & FD_MSR_NONDMA)) {
22
+ if (bdrv_pwrite(extent->file,
40
IsaDmaClass *k = ISADMA_GET_CLASS(fdctrl->dma);
23
((int64_t)m_data->l2_offset * 512)
41
k->release_DREQ(fdctrl->dma, fdctrl->dma_chann);
24
+ (m_data->l2_index * sizeof(offset)),
25
&offset, sizeof(offset)) < 0) {
26
@@ -XXX,XX +XXX,XX @@ static int vmdk_L2update(VmdkExtent *extent, VmdkMetaData *m_data,
27
/* update backup L2 table */
28
if (extent->l1_backup_table_offset != 0) {
29
m_data->l2_offset = extent->l1_backup_table[m_data->l1_index];
30
- if (bdrv_pwrite_sync(extent->file,
31
+ if (bdrv_pwrite(extent->file,
32
((int64_t)m_data->l2_offset * 512)
33
+ (m_data->l2_index * sizeof(offset)),
34
&offset, sizeof(offset)) < 0) {
35
return VMDK_ERROR;
36
}
37
}
38
+ if (bdrv_flush(extent->file->bs) < 0) {
39
+ return VMDK_ERROR;
40
+ }
41
if (m_data->l2_cache_entry) {
42
*m_data->l2_cache_entry = offset;
42
}
43
}
43
--
44
--
44
2.19.1
45
2.25.3
45
46
46
47
diff view generated by jsdifflib
New patch
1
In order to avoid bitrot in the zero cluster code in VMDK, enable
2
zeroed_grain=on by default for the tests.
1
3
4
059 now unsets the default options because zeroed_grain=on works only
5
with some subformats and the test case tests many different subformats,
6
including those for which it doesn't work.
7
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Message-Id: <20200430133007.170335-7-kwolf@redhat.com>
10
Reviewed-by: Eric Blake <eblake@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
---
13
tests/qemu-iotests/059 | 6 +++---
14
tests/qemu-iotests/check | 3 +++
15
2 files changed, 6 insertions(+), 3 deletions(-)
16
17
diff --git a/tests/qemu-iotests/059 b/tests/qemu-iotests/059
18
index XXXXXXX..XXXXXXX 100755
19
--- a/tests/qemu-iotests/059
20
+++ b/tests/qemu-iotests/059
21
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
22
_supported_fmt vmdk
23
_supported_proto file
24
_supported_os Linux
25
-_unsupported_imgopts "subformat=monolithicFlat" \
26
- "subformat=twoGbMaxExtentFlat" \
27
- "subformat=twoGbMaxExtentSparse"
28
+
29
+# We test all kinds of VMDK options here, so ignore user-specified options
30
+IMGOPTS=""
31
32
capacity_offset=16
33
granularity_offset=20
34
diff --git a/tests/qemu-iotests/check b/tests/qemu-iotests/check
35
index XXXXXXX..XXXXXXX 100755
36
--- a/tests/qemu-iotests/check
37
+++ b/tests/qemu-iotests/check
38
@@ -XXX,XX +XXX,XX @@ fi
39
if [ "$IMGFMT" == "luks" ] && ! (echo "$IMGOPTS" | grep "iter-time=" > /dev/null); then
40
IMGOPTS=$(_optstr_add "$IMGOPTS" "iter-time=10")
41
fi
42
+if [ "$IMGFMT" == "vmdk" ] && ! (echo "$IMGOPTS" | grep "zeroed_grain=" > /dev/null); then
43
+ IMGOPTS=$(_optstr_add "$IMGOPTS" "zeroed_grain=on")
44
+fi
45
46
if [ -z "$SAMPLE_IMG_DIR" ]; then
47
SAMPLE_IMG_DIR="$source_iotests/sample_images"
48
--
49
2.25.3
50
51
diff view generated by jsdifflib
New patch
1
The test case forgot to specify the null-co size for the target node.
2
When adding a check to backup that both sizes match, this would fail
3
because of the size mismatch and not the behaviour that the test really
4
wanted to test.
1
5
6
Fixes: a541fcc27c98b96da187c7d4573f3270f3ddd283
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
Message-Id: <20200430142755.315494-2-kwolf@redhat.com>
9
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
---
12
tests/qemu-iotests/283 | 6 +++++-
13
tests/qemu-iotests/283.out | 2 +-
14
2 files changed, 6 insertions(+), 2 deletions(-)
15
16
diff --git a/tests/qemu-iotests/283 b/tests/qemu-iotests/283
17
index XXXXXXX..XXXXXXX 100644
18
--- a/tests/qemu-iotests/283
19
+++ b/tests/qemu-iotests/283
20
@@ -XXX,XX +XXX,XX @@ to check that crash is fixed :)
21
vm = iotests.VM()
22
vm.launch()
23
24
-vm.qmp_log('blockdev-add', **{'node-name': 'target', 'driver': 'null-co'})
25
+vm.qmp_log('blockdev-add', **{
26
+ 'node-name': 'target',
27
+ 'driver': 'null-co',
28
+ 'size': size,
29
+})
30
31
vm.qmp_log('blockdev-add', **{
32
'node-name': 'source',
33
diff --git a/tests/qemu-iotests/283.out b/tests/qemu-iotests/283.out
34
index XXXXXXX..XXXXXXX 100644
35
--- a/tests/qemu-iotests/283.out
36
+++ b/tests/qemu-iotests/283.out
37
@@ -XXX,XX +XXX,XX @@
38
-{"execute": "blockdev-add", "arguments": {"driver": "null-co", "node-name": "target"}}
39
+{"execute": "blockdev-add", "arguments": {"driver": "null-co", "node-name": "target", "size": 1048576}}
40
{"return": {}}
41
{"execute": "blockdev-add", "arguments": {"driver": "blkdebug", "image": {"driver": "null-co", "node-name": "base", "size": 1048576}, "node-name": "source"}}
42
{"return": {}}
43
--
44
2.25.3
45
46
diff view generated by jsdifflib
New patch
1
bdrv_get_device_name() will be an empty string with modern management
2
tools that don't use -drive. Use bdrv_get_device_or_node_name() instead
3
so that the node name is used if the BlockBackend is anonymous.
1
4
5
While at it, start with upper case to make the message consistent with
6
the rest of the function.
7
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
10
Reviewed-by: Alberto Garcia <berto@igalia.com>
11
Message-Id: <20200430142755.315494-3-kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
---
14
block/backup.c | 4 ++--
15
1 file changed, 2 insertions(+), 2 deletions(-)
16
17
diff --git a/block/backup.c b/block/backup.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/block/backup.c
20
+++ b/block/backup.c
21
@@ -XXX,XX +XXX,XX @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
22
23
len = bdrv_getlength(bs);
24
if (len < 0) {
25
- error_setg_errno(errp, -len, "unable to get length for '%s'",
26
- bdrv_get_device_name(bs));
27
+ error_setg_errno(errp, -len, "Unable to get length for '%s'",
28
+ bdrv_get_device_or_node_name(bs));
29
goto error;
30
}
31
32
--
33
2.25.3
34
35
diff view generated by jsdifflib
New patch
1
Since the introduction of a backup filter node in commit 00e30f05d, the
2
backup block job crashes when the target image is smaller than the
3
source image because it will try to write after the end of the target
4
node without having BLK_PERM_RESIZE. (Previously, the BlockBackend layer
5
would have caught this and errored out gracefully.)
1
6
7
We can fix this and even do better than the old behaviour: Check that
8
source and target have the same image size at the start of the block job
9
and unshare BLK_PERM_RESIZE. (This permission was already unshared
10
before the same commit 00e30f05d, but the BlockBackend that was used to
11
make the restriction was removed without a replacement.) This will
12
immediately error out when starting the job instead of only when writing
13
to a block that doesn't exist in the target.
14
15
Longer target than source would technically work because we would never
16
write to blocks that don't exist, but semantically these are invalid,
17
too, because a backup is supposed to create a copy, not just an image
18
that starts with a copy.
19
20
Fixes: 00e30f05de1d19586345ec373970ef4c192c6270
21
Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1778593
22
Cc: qemu-stable@nongnu.org
23
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
24
Message-Id: <20200430142755.315494-4-kwolf@redhat.com>
25
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
26
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
27
---
28
block/backup-top.c | 14 +++++++++-----
29
block/backup.c | 14 +++++++++++++-
30
2 files changed, 22 insertions(+), 6 deletions(-)
31
32
diff --git a/block/backup-top.c b/block/backup-top.c
33
index XXXXXXX..XXXXXXX 100644
34
--- a/block/backup-top.c
35
+++ b/block/backup-top.c
36
@@ -XXX,XX +XXX,XX @@ static void backup_top_child_perm(BlockDriverState *bs, BdrvChild *c,
37
*
38
* Share write to target (child_file), to not interfere
39
* with guest writes to its disk which may be in target backing chain.
40
+ * Can't resize during a backup block job because we check the size
41
+ * only upfront.
42
*/
43
- *nshared = BLK_PERM_ALL;
44
+ *nshared = BLK_PERM_ALL & ~BLK_PERM_RESIZE;
45
*nperm = BLK_PERM_WRITE;
46
} else {
47
/* Source child */
48
@@ -XXX,XX +XXX,XX @@ static void backup_top_child_perm(BlockDriverState *bs, BdrvChild *c,
49
if (perm & BLK_PERM_WRITE) {
50
*nperm = *nperm | BLK_PERM_CONSISTENT_READ;
51
}
52
- *nshared &= ~BLK_PERM_WRITE;
53
+ *nshared &= ~(BLK_PERM_WRITE | BLK_PERM_RESIZE);
54
}
55
}
56
57
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_backup_top_append(BlockDriverState *source,
58
{
59
Error *local_err = NULL;
60
BDRVBackupTopState *state;
61
- BlockDriverState *top = bdrv_new_open_driver(&bdrv_backup_top_filter,
62
- filter_node_name,
63
- BDRV_O_RDWR, errp);
64
+ BlockDriverState *top;
65
bool appended = false;
66
67
+ assert(source->total_sectors == target->total_sectors);
68
+
69
+ top = bdrv_new_open_driver(&bdrv_backup_top_filter, filter_node_name,
70
+ BDRV_O_RDWR, errp);
71
if (!top) {
72
return NULL;
73
}
74
diff --git a/block/backup.c b/block/backup.c
75
index XXXXXXX..XXXXXXX 100644
76
--- a/block/backup.c
77
+++ b/block/backup.c
78
@@ -XXX,XX +XXX,XX @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
79
BlockCompletionFunc *cb, void *opaque,
80
JobTxn *txn, Error **errp)
81
{
82
- int64_t len;
83
+ int64_t len, target_len;
84
BackupBlockJob *job = NULL;
85
int64_t cluster_size;
86
BdrvRequestFlags write_flags;
87
@@ -XXX,XX +XXX,XX @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
88
goto error;
89
}
90
91
+ target_len = bdrv_getlength(target);
92
+ if (target_len < 0) {
93
+ error_setg_errno(errp, -target_len, "Unable to get length for '%s'",
94
+ bdrv_get_device_or_node_name(bs));
95
+ goto error;
96
+ }
97
+
98
+ if (target_len != len) {
99
+ error_setg(errp, "Source and target image have different sizes");
100
+ goto error;
101
+ }
102
+
103
cluster_size = backup_calculate_cluster_size(target, errp);
104
if (cluster_size < 0) {
105
goto error;
106
--
107
2.25.3
108
109
diff view generated by jsdifflib
New patch
1
This tests that the backup job catches situations where the target node
2
has a different size than the source node. It must also forbid resize
3
operations when the job is already running.
1
4
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
Message-Id: <20200430142755.315494-5-kwolf@redhat.com>
7
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
10
tests/qemu-iotests/055 | 41 ++++++++++++++++++++++++++++++++++++--
11
tests/qemu-iotests/055.out | 4 ++--
12
2 files changed, 41 insertions(+), 4 deletions(-)
13
14
diff --git a/tests/qemu-iotests/055 b/tests/qemu-iotests/055
15
index XXXXXXX..XXXXXXX 100755
16
--- a/tests/qemu-iotests/055
17
+++ b/tests/qemu-iotests/055
18
@@ -XXX,XX +XXX,XX @@ class TestSingleDrive(iotests.QMPTestCase):
19
def setUp(self):
20
qemu_img('create', '-f', iotests.imgfmt, blockdev_target_img, str(image_len))
21
22
- self.vm = iotests.VM().add_drive('blkdebug::' + test_img)
23
- self.vm.add_drive(blockdev_target_img, interface="none")
24
+ self.vm = iotests.VM()
25
+ self.vm.add_drive('blkdebug::' + test_img, 'node-name=source')
26
+ self.vm.add_drive(blockdev_target_img, 'node-name=target',
27
+ interface="none")
28
if iotests.qemu_default_machine == 'pc':
29
self.vm.add_drive(None, 'media=cdrom', 'ide')
30
self.vm.launch()
31
@@ -XXX,XX +XXX,XX @@ class TestSingleDrive(iotests.QMPTestCase):
32
def test_pause_blockdev_backup(self):
33
self.do_test_pause('blockdev-backup', 'drive1', blockdev_target_img)
34
35
+ def do_test_resize_blockdev_backup(self, device, node):
36
+ def pre_finalize():
37
+ result = self.vm.qmp('block_resize', device=device, size=65536)
38
+ self.assert_qmp(result, 'error/class', 'GenericError')
39
+
40
+ result = self.vm.qmp('block_resize', node_name=node, size=65536)
41
+ self.assert_qmp(result, 'error/class', 'GenericError')
42
+
43
+ result = self.vm.qmp('blockdev-backup', job_id='job0', device='drive0',
44
+ target='drive1', sync='full', auto_finalize=False,
45
+ auto_dismiss=False)
46
+ self.assert_qmp(result, 'return', {})
47
+
48
+ self.vm.run_job('job0', auto_finalize=False, pre_finalize=pre_finalize)
49
+
50
+ def test_source_resize_blockdev_backup(self):
51
+ self.do_test_resize_blockdev_backup('drive0', 'source')
52
+
53
+ def test_target_resize_blockdev_backup(self):
54
+ self.do_test_resize_blockdev_backup('drive1', 'target')
55
+
56
+ def do_test_target_size(self, size):
57
+ result = self.vm.qmp('block_resize', device='drive1', size=size)
58
+ self.assert_qmp(result, 'return', {})
59
+
60
+ result = self.vm.qmp('blockdev-backup', job_id='job0', device='drive0',
61
+ target='drive1', sync='full')
62
+ self.assert_qmp(result, 'error/class', 'GenericError')
63
+
64
+ def test_small_target(self):
65
+ self.do_test_target_size(image_len // 2)
66
+
67
+ def test_large_target(self):
68
+ self.do_test_target_size(image_len * 2)
69
+
70
def test_medium_not_found(self):
71
if iotests.qemu_default_machine != 'pc':
72
return
73
diff --git a/tests/qemu-iotests/055.out b/tests/qemu-iotests/055.out
74
index XXXXXXX..XXXXXXX 100644
75
--- a/tests/qemu-iotests/055.out
76
+++ b/tests/qemu-iotests/055.out
77
@@ -XXX,XX +XXX,XX @@
78
-....................................
79
+........................................
80
----------------------------------------------------------------------
81
-Ran 36 tests
82
+Ran 40 tests
83
84
OK
85
--
86
2.25.3
87
88
diff view generated by jsdifflib
New patch
1
055 uses the backup block job to create a compressed backup of an
2
$IMGFMT image with both qcow2 and vmdk targets. However, cluster
3
allocation in vmdk is very slow because it flushes the image file after
4
each L2 update.
1
5
6
There is no reason why we need this level of safety in this test, so
7
let's disable flushes for vmdk. For the blockdev-backup tests this is
8
achieved by simply adding the cache.no-flush=on to the drive_add() for
9
the target. For drive-backup, the caching flags are copied from the
10
source node, so we'll also add the flag to the source node, even though
11
it is not vmdk.
12
13
This can make the test run significantly faster (though it doesn't make
14
a difference on tmpfs). In my usual setup it goes from ~45s to ~15s.
15
16
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
17
Message-Id: <20200505064618.16267-1-kwolf@redhat.com>
18
Reviewed-by: Eric Blake <eblake@redhat.com>
19
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
20
---
21
tests/qemu-iotests/055 | 11 +++++++----
22
1 file changed, 7 insertions(+), 4 deletions(-)
23
24
diff --git a/tests/qemu-iotests/055 b/tests/qemu-iotests/055
25
index XXXXXXX..XXXXXXX 100755
26
--- a/tests/qemu-iotests/055
27
+++ b/tests/qemu-iotests/055
28
@@ -XXX,XX +XXX,XX @@ class TestSingleTransaction(iotests.QMPTestCase):
29
30
class TestCompressedToQcow2(iotests.QMPTestCase):
31
image_len = 64 * 1024 * 1024 # MB
32
- target_fmt = {'type': 'qcow2', 'args': ()}
33
+ target_fmt = {'type': 'qcow2', 'args': (), 'drive-opts': ''}
34
35
def tearDown(self):
36
self.vm.shutdown()
37
@@ -XXX,XX +XXX,XX @@ class TestCompressedToQcow2(iotests.QMPTestCase):
38
pass
39
40
def do_prepare_drives(self, attach_target):
41
- self.vm = iotests.VM().add_drive('blkdebug::' + test_img)
42
+ self.vm = iotests.VM().add_drive('blkdebug::' + test_img,
43
+ opts=self.target_fmt['drive-opts'])
44
45
qemu_img('create', '-f', self.target_fmt['type'], blockdev_target_img,
46
str(self.image_len), *self.target_fmt['args'])
47
if attach_target:
48
self.vm.add_drive(blockdev_target_img,
49
img_format=self.target_fmt['type'],
50
- interface="none")
51
+ interface="none",
52
+ opts=self.target_fmt['drive-opts'])
53
54
self.vm.launch()
55
56
@@ -XXX,XX +XXX,XX @@ class TestCompressedToQcow2(iotests.QMPTestCase):
57
58
59
class TestCompressedToVmdk(TestCompressedToQcow2):
60
- target_fmt = {'type': 'vmdk', 'args': ('-o', 'subformat=streamOptimized')}
61
+ target_fmt = {'type': 'vmdk', 'args': ('-o', 'subformat=streamOptimized'),
62
+ 'drive-opts': 'cache.no-flush=on'}
63
64
@iotests.skip_if_unsupported(['vmdk'])
65
def setUp(self):
66
--
67
2.25.3
68
69
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Max Reitz <mreitz@redhat.com>
2
2
3
Calling bdrv_getlength() to get the pre-truncate file size will not
4
really work on block devices, because they have always the same length,
5
and trying to write beyond it will fail with a rather cryptic error
6
message.
7
8
Instead, we should use qcow2_get_last_cluster() and bdrv_getlength()
9
only as a fallback.
10
11
Before this patch:
12
$ truncate -s 1G test.img
13
$ sudo losetup -f --show test.img
14
/dev/loop0
15
$ sudo qemu-img create -f qcow2 -o preallocation=full /dev/loop0 64M
16
Formatting '/dev/loop0', fmt=qcow2 size=67108864 cluster_size=65536
17
preallocation=full lazy_refcounts=off refcount_bits=16
18
qemu-img: /dev/loop0: Could not resize image: Failed to resize refcount
19
structures: No space left on device
20
21
With this patch:
22
$ sudo qemu-img create -f qcow2 -o preallocation=full /dev/loop0 64M
23
Formatting '/dev/loop0', fmt=qcow2 size=67108864 cluster_size=65536
24
preallocation=full lazy_refcounts=off refcount_bits=16
25
qemu-img: /dev/loop0: Could not resize image: Failed to resize
26
underlying file: Preallocation mode 'full' unsupported for this
27
non-regular file
28
29
So as you can see, it still fails, but now the problem is missing
30
support on the block device level, so we at least get a better error
31
message.
32
33
Note that we cannot preallocate block devices on truncate by design,
34
because we do not know what area to preallocate. Their length is always
35
the same, the truncate operation does not change it.
36
3
Signed-off-by: Max Reitz <mreitz@redhat.com>
37
Signed-off-by: Max Reitz <mreitz@redhat.com>
4
Reviewed-by: Alberto Garcia <berto@igalia.com>
38
Message-Id: <20200505141801.1096763-1-mreitz@redhat.com>
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
39
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
---
40
---
7
tests/qemu-iotests/182 | 71 ++++++++++++++++++++++++++++++++++++++
41
block/qcow2.c | 10 ++++++++--
8
tests/qemu-iotests/182.out | 9 +++++
42
1 file changed, 8 insertions(+), 2 deletions(-)
9
2 files changed, 80 insertions(+)
10
43
11
diff --git a/tests/qemu-iotests/182 b/tests/qemu-iotests/182
44
diff --git a/block/qcow2.c b/block/qcow2.c
12
index XXXXXXX..XXXXXXX 100755
45
index XXXXXXX..XXXXXXX 100644
13
--- a/tests/qemu-iotests/182
46
--- a/block/qcow2.c
14
+++ b/tests/qemu-iotests/182
47
+++ b/block/qcow2.c
15
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
48
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
16
_cleanup()
49
{
17
{
50
int64_t allocation_start, host_offset, guest_offset;
18
_cleanup_test_img
51
int64_t clusters_allocated;
19
+ rm -f "$TEST_IMG.overlay"
52
- int64_t old_file_size, new_file_size;
20
}
53
+ int64_t old_file_size, last_cluster, new_file_size;
21
trap "_cleanup; exit \$status" 0 1 2 3 15
54
uint64_t nb_new_data_clusters, nb_new_l2_tables;
22
55
23
@@ -XXX,XX +XXX,XX @@ echo 'quit' | $QEMU -nographic -monitor stdio \
56
/* With a data file, preallocation means just allocating the metadata
24
57
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
25
_cleanup_qemu
58
ret = old_file_size;
26
59
goto fail;
27
+echo
60
}
28
+echo '=== Testing reopen ==='
61
- old_file_size = ROUND_UP(old_file_size, s->cluster_size);
29
+echo
30
+
62
+
31
+# This tests that reopening does not unshare any permissions it should
63
+ last_cluster = qcow2_get_last_cluster(bs, old_file_size);
32
+# not unshare
64
+ if (last_cluster >= 0) {
33
+# (There was a bug where reopening shared exactly the opposite of the
65
+ old_file_size = (last_cluster + 1) * s->cluster_size;
34
+# permissions it was supposed to share)
66
+ } else {
35
+
67
+ old_file_size = ROUND_UP(old_file_size, s->cluster_size);
36
+_launch_qemu
68
+ }
37
+
69
38
+_send_qemu_cmd $QEMU_HANDLE \
70
nb_new_data_clusters = DIV_ROUND_UP(offset - old_length,
39
+ "{'execute': 'qmp_capabilities'}" \
71
s->cluster_size);
40
+ 'return'
41
+
42
+# Open the image without any format layer (we are not going to access
43
+# it, so that is fine)
44
+# This should keep all permissions shared.
45
+success_or_failure=y _send_qemu_cmd $QEMU_HANDLE \
46
+ "{'execute': 'blockdev-add',
47
+ 'arguments': {
48
+ 'node-name': 'node0',
49
+ 'driver': 'file',
50
+ 'filename': '$TEST_IMG',
51
+ 'locking': 'on'
52
+ } }" \
53
+ 'return' \
54
+ 'error'
55
+
56
+# This snapshot will perform a reopen to drop R/W to RO.
57
+# It should still keep all permissions shared.
58
+success_or_failure=y _send_qemu_cmd $QEMU_HANDLE \
59
+ "{'execute': 'blockdev-snapshot-sync',
60
+ 'arguments': {
61
+ 'node-name': 'node0',
62
+ 'snapshot-file': '$TEST_IMG.overlay',
63
+ 'snapshot-node-name': 'node1'
64
+ } }" \
65
+ 'return' \
66
+ 'error'
67
+
68
+# Now open the same file again
69
+# This does not require any permissions (and does not unshare any), so
70
+# this will not conflict with node0.
71
+success_or_failure=y _send_qemu_cmd $QEMU_HANDLE \
72
+ "{'execute': 'blockdev-add',
73
+ 'arguments': {
74
+ 'node-name': 'node1',
75
+ 'driver': 'file',
76
+ 'filename': '$TEST_IMG',
77
+ 'locking': 'on'
78
+ } }" \
79
+ 'return' \
80
+ 'error'
81
+
82
+# Now we attach the image to a virtio-blk device. This device does
83
+# require some permissions (at least WRITE and READ_CONSISTENT), so if
84
+# reopening node0 unshared any (which it should not have), this will
85
+# fail (but it should not).
86
+success_or_failure=y _send_qemu_cmd $QEMU_HANDLE \
87
+ "{'execute': 'device_add',
88
+ 'arguments': {
89
+ 'driver': 'virtio-blk',
90
+ 'drive': 'node1'
91
+ } }" \
92
+ 'return' \
93
+ 'error'
94
+
95
+_cleanup_qemu
96
+
97
# success, all done
98
echo "*** done"
99
rm -f $seq.full
100
diff --git a/tests/qemu-iotests/182.out b/tests/qemu-iotests/182.out
101
index XXXXXXX..XXXXXXX 100644
102
--- a/tests/qemu-iotests/182.out
103
+++ b/tests/qemu-iotests/182.out
104
@@ -XXX,XX +XXX,XX @@ Starting QEMU
105
Starting a second QEMU using the same image should fail
106
QEMU_PROG: -drive file=TEST_DIR/t.qcow2,if=none,id=drive0,file.locking=on: Failed to get "write" lock
107
Is another process using the image [TEST_DIR/t.qcow2]?
108
+
109
+=== Testing reopen ===
110
+
111
+{"return": {}}
112
+{"return": {}}
113
+Formatting 'TEST_DIR/t.qcow2.overlay', fmt=qcow2 size=197120 backing_file=TEST_DIR/t.qcow2 backing_fmt=file cluster_size=65536 lazy_refcounts=off refcount_bits=16
114
+{"return": {}}
115
+{"return": {}}
116
+{"return": {}}
117
*** done
118
--
72
--
119
2.19.1
73
2.25.3
120
74
121
75
diff view generated by jsdifflib
1
From: Li Qiang <liq3ea@gmail.com>
1
From: Eric Blake <eblake@redhat.com>
2
2
3
Currently, the nvme_cmb_ops mr doesn't check the addr and size.
3
block.c already defaults to 0 if we don't provide a callback; there's
4
This can lead an oob access issue. This is triggerable in the guest.
4
no need to write a callback that always fails.
5
Add check to avoid this issue.
6
5
7
Fixes CVE-2018-16847.
6
Signed-off-by: Eric Blake <eblake@redhat.com>
8
7
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
9
Reported-by: Li Qiang <liq3ea@gmail.com>
8
Reviewed-by: Alberto Garcia <berto@igalia.com>
10
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
9
Message-Id: <20200428202905.770727-2-eblake@redhat.com>
11
Signed-off-by: Li Qiang <liq3ea@gmail.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
---
11
---
14
hw/block/nvme.c | 7 +++++++
12
block/gluster.c | 14 --------------
15
1 file changed, 7 insertions(+)
13
1 file changed, 14 deletions(-)
16
14
17
diff --git a/hw/block/nvme.c b/hw/block/nvme.c
15
diff --git a/block/gluster.c b/block/gluster.c
18
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/block/nvme.c
17
--- a/block/gluster.c
20
+++ b/hw/block/nvme.c
18
+++ b/block/gluster.c
21
@@ -XXX,XX +XXX,XX @@ static void nvme_cmb_write(void *opaque, hwaddr addr, uint64_t data,
19
@@ -XXX,XX +XXX,XX @@ static int64_t qemu_gluster_allocated_file_size(BlockDriverState *bs)
22
unsigned size)
20
}
23
{
24
NvmeCtrl *n = (NvmeCtrl *)opaque;
25
+
26
+ if (addr + size > NVME_CMBSZ_GETSIZE(n->bar.cmbsz)) {
27
+ return;
28
+ }
29
memcpy(&n->cmbuf[addr], &data, size);
30
}
21
}
31
22
32
@@ -XXX,XX +XXX,XX @@ static uint64_t nvme_cmb_read(void *opaque, hwaddr addr, unsigned size)
23
-static int qemu_gluster_has_zero_init(BlockDriverState *bs)
33
uint64_t val;
24
-{
34
NvmeCtrl *n = (NvmeCtrl *)opaque;
25
- /* GlusterFS volume could be backed by a block device */
35
26
- return 0;
36
+ if (addr + size > NVME_CMBSZ_GETSIZE(n->bar.cmbsz)) {
27
-}
37
+ return 0;
28
-
38
+ }
29
/*
39
memcpy(&val, &n->cmbuf[addr], size);
30
* Find allocation range in @bs around offset @start.
40
return val;
31
* May change underlying file descriptor's file offset.
41
}
32
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_gluster = {
33
.bdrv_co_readv = qemu_gluster_co_readv,
34
.bdrv_co_writev = qemu_gluster_co_writev,
35
.bdrv_co_flush_to_disk = qemu_gluster_co_flush_to_disk,
36
- .bdrv_has_zero_init = qemu_gluster_has_zero_init,
37
- .bdrv_has_zero_init_truncate = qemu_gluster_has_zero_init,
38
#ifdef CONFIG_GLUSTERFS_DISCARD
39
.bdrv_co_pdiscard = qemu_gluster_co_pdiscard,
40
#endif
41
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_gluster_tcp = {
42
.bdrv_co_readv = qemu_gluster_co_readv,
43
.bdrv_co_writev = qemu_gluster_co_writev,
44
.bdrv_co_flush_to_disk = qemu_gluster_co_flush_to_disk,
45
- .bdrv_has_zero_init = qemu_gluster_has_zero_init,
46
- .bdrv_has_zero_init_truncate = qemu_gluster_has_zero_init,
47
#ifdef CONFIG_GLUSTERFS_DISCARD
48
.bdrv_co_pdiscard = qemu_gluster_co_pdiscard,
49
#endif
50
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_gluster_unix = {
51
.bdrv_co_readv = qemu_gluster_co_readv,
52
.bdrv_co_writev = qemu_gluster_co_writev,
53
.bdrv_co_flush_to_disk = qemu_gluster_co_flush_to_disk,
54
- .bdrv_has_zero_init = qemu_gluster_has_zero_init,
55
- .bdrv_has_zero_init_truncate = qemu_gluster_has_zero_init,
56
#ifdef CONFIG_GLUSTERFS_DISCARD
57
.bdrv_co_pdiscard = qemu_gluster_co_pdiscard,
58
#endif
59
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_gluster_rdma = {
60
.bdrv_co_readv = qemu_gluster_co_readv,
61
.bdrv_co_writev = qemu_gluster_co_writev,
62
.bdrv_co_flush_to_disk = qemu_gluster_co_flush_to_disk,
63
- .bdrv_has_zero_init = qemu_gluster_has_zero_init,
64
- .bdrv_has_zero_init_truncate = qemu_gluster_has_zero_init,
65
#ifdef CONFIG_GLUSTERFS_DISCARD
66
.bdrv_co_pdiscard = qemu_gluster_co_pdiscard,
67
#endif
42
--
68
--
43
2.19.1
69
2.25.3
44
70
45
71
diff view generated by jsdifflib
New patch
1
From: Eric Blake <eblake@redhat.com>
1
2
3
When using bdrv_file, .bdrv_has_zero_init_truncate always returns 1;
4
therefore, we can behave just like file-posix, and always implement
5
BDRV_REQ_ZERO_WRITE by ignoring it since the OS gives it to us for
6
free (note that file-posix.c had to use an 'if' because it shared code
7
between regular files and block devices, but in file-win32.c,
8
bdrv_host_device uses a separate .bdrv_file_open).
9
10
Signed-off-by: Eric Blake <eblake@redhat.com>
11
Message-Id: <20200428202905.770727-3-eblake@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
---
14
block/file-win32.c | 3 +++
15
1 file changed, 3 insertions(+)
16
17
diff --git a/block/file-win32.c b/block/file-win32.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/block/file-win32.c
20
+++ b/block/file-win32.c
21
@@ -XXX,XX +XXX,XX @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags,
22
win32_aio_attach_aio_context(s->aio, bdrv_get_aio_context(bs));
23
}
24
25
+ /* When extending regular files, we get zeros from the OS */
26
+ bs->supported_truncate_flags = BDRV_REQ_ZERO_WRITE;
27
+
28
ret = 0;
29
fail:
30
qemu_opts_del(opts);
31
--
32
2.25.3
33
34
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
1
From: Eric Blake <eblake@redhat.com>
2
2
3
Our code was already checking that we did not attempt to
3
Our .bdrv_has_zero_init_truncate returns 1 if we detect that the OS
4
allocate more clusters than what would fit in an INT64 (the
4
always 0-fills; we can use that same knowledge to implement
5
physical maximimum if we can access a full off_t's worth of
5
BDRV_REQ_ZERO_WRITE by ignoring it when the OS gives it to us for
6
data). But this does not catch smaller limits enforced by
6
free.
7
various spots in the qcow2 image description: L1 and normal
8
clusters of L2 are documented as having bits 63-56 reserved
9
for other purposes, capping our maximum offset at 64PB (bit
10
55 is the maximum bit set). And for compressed images with
11
2M clusters, the cap drops the maximum offset to bit 48, or
12
a maximum offset of 512TB. If we overflow that offset, we
13
would write compressed data into one place, but try to
14
decompress from another, which won't work.
15
16
It's actually possible to prove that overflow can cause image
17
corruption without this patch; I'll add the iotests separately
18
in the next commit.
19
7
20
Signed-off-by: Eric Blake <eblake@redhat.com>
8
Signed-off-by: Eric Blake <eblake@redhat.com>
21
Reviewed-by: Alberto Garcia <berto@igalia.com>
9
Message-Id: <20200428202905.770727-4-eblake@redhat.com>
22
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
23
---
11
---
24
block/qcow2.h | 6 ++++++
12
block/nfs.c | 3 +++
25
block/qcow2-refcount.c | 20 +++++++++++++-------
13
1 file changed, 3 insertions(+)
26
2 files changed, 19 insertions(+), 7 deletions(-)
27
14
28
diff --git a/block/qcow2.h b/block/qcow2.h
15
diff --git a/block/nfs.c b/block/nfs.c
29
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
30
--- a/block/qcow2.h
17
--- a/block/nfs.c
31
+++ b/block/qcow2.h
18
+++ b/block/nfs.c
32
@@ -XXX,XX +XXX,XX @@
19
@@ -XXX,XX +XXX,XX @@ static int nfs_file_open(BlockDriverState *bs, QDict *options, int flags,
33
#define QCOW_MAX_CRYPT_CLUSTERS 32
34
#define QCOW_MAX_SNAPSHOTS 65536
35
36
+/* Field widths in qcow2 mean normal cluster offsets cannot reach
37
+ * 64PB; depending on cluster size, compressed clusters can have a
38
+ * smaller limit (64PB for up to 16k clusters, then ramps down to
39
+ * 512TB for 2M clusters). */
40
+#define QCOW_MAX_CLUSTER_OFFSET ((1ULL << 56) - 1)
41
+
42
/* 8 MB refcount table is enough for 2 PB images at 64k cluster size
43
* (128 GB for 512 byte clusters, 2 EB for 2 MB clusters) */
44
#define QCOW_MAX_REFTABLE_SIZE S_8MiB
45
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
46
index XXXXXXX..XXXXXXX 100644
47
--- a/block/qcow2-refcount.c
48
+++ b/block/qcow2-refcount.c
49
@@ -XXX,XX +XXX,XX @@
50
#include "qemu/bswap.h"
51
#include "qemu/cutils.h"
52
53
-static int64_t alloc_clusters_noref(BlockDriverState *bs, uint64_t size);
54
+static int64_t alloc_clusters_noref(BlockDriverState *bs, uint64_t size,
55
+ uint64_t max);
56
static int QEMU_WARN_UNUSED_RESULT update_refcount(BlockDriverState *bs,
57
int64_t offset, int64_t length, uint64_t addend,
58
bool decrease, enum qcow2_discard_type type);
59
@@ -XXX,XX +XXX,XX @@ static int alloc_refcount_block(BlockDriverState *bs,
60
}
20
}
61
21
62
/* Allocate the refcount block itself and mark it as used */
22
bs->total_sectors = ret;
63
- int64_t new_block = alloc_clusters_noref(bs, s->cluster_size);
23
+ if (client->has_zero_init) {
64
+ int64_t new_block = alloc_clusters_noref(bs, s->cluster_size, INT64_MAX);
24
+ bs->supported_truncate_flags = BDRV_REQ_ZERO_WRITE;
65
if (new_block < 0) {
25
+ }
66
return new_block;
26
return 0;
67
}
27
}
68
@@ -XXX,XX +XXX,XX @@ int qcow2_update_cluster_refcount(BlockDriverState *bs,
28
69
70
71
/* return < 0 if error */
72
-static int64_t alloc_clusters_noref(BlockDriverState *bs, uint64_t size)
73
+static int64_t alloc_clusters_noref(BlockDriverState *bs, uint64_t size,
74
+ uint64_t max)
75
{
76
BDRVQcow2State *s = bs->opaque;
77
uint64_t i, nb_clusters, refcount;
78
@@ -XXX,XX +XXX,XX @@ retry:
79
}
80
81
/* Make sure that all offsets in the "allocated" range are representable
82
- * in an int64_t */
83
+ * in the requested max */
84
if (s->free_cluster_index > 0 &&
85
- s->free_cluster_index - 1 > (INT64_MAX >> s->cluster_bits))
86
+ s->free_cluster_index - 1 > (max >> s->cluster_bits))
87
{
88
return -EFBIG;
89
}
90
@@ -XXX,XX +XXX,XX @@ int64_t qcow2_alloc_clusters(BlockDriverState *bs, uint64_t size)
91
92
BLKDBG_EVENT(bs->file, BLKDBG_CLUSTER_ALLOC);
93
do {
94
- offset = alloc_clusters_noref(bs, size);
95
+ offset = alloc_clusters_noref(bs, size, QCOW_MAX_CLUSTER_OFFSET);
96
if (offset < 0) {
97
return offset;
98
}
99
@@ -XXX,XX +XXX,XX @@ int64_t qcow2_alloc_bytes(BlockDriverState *bs, int size)
100
free_in_cluster = s->cluster_size - offset_into_cluster(s, offset);
101
do {
102
if (!offset || free_in_cluster < size) {
103
- int64_t new_cluster = alloc_clusters_noref(bs, s->cluster_size);
104
+ int64_t new_cluster;
105
+
106
+ new_cluster = alloc_clusters_noref(bs, s->cluster_size,
107
+ MIN(s->cluster_offset_mask,
108
+ QCOW_MAX_CLUSTER_OFFSET));
109
if (new_cluster < 0) {
110
return new_cluster;
111
}
112
--
29
--
113
2.19.1
30
2.25.3
114
31
115
32
diff view generated by jsdifflib
1
Don't leak 'cluster' in the mapping == NULL case. Found by Coverity
1
From: Eric Blake <eblake@redhat.com>
2
(CID 1055918).
3
2
4
Fixes: 8d9401c2791ee2d2805b741b1ee3006041edcd3e
3
Our .bdrv_has_zero_init_truncate always returns 1 because rbd always
4
0-fills; we can use that same knowledge to implement
5
BDRV_REQ_ZERO_WRITE by ignoring it.
6
7
Signed-off-by: Eric Blake <eblake@redhat.com>
8
Message-Id: <20200428202905.770727-5-eblake@redhat.com>
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
7
Reviewed-by: Liam Merwick <liam.merwick@oracle.com>
8
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
9
---
10
---
10
block/vvfat.c | 6 +++---
11
block/rbd.c | 3 +++
11
1 file changed, 3 insertions(+), 3 deletions(-)
12
1 file changed, 3 insertions(+)
12
13
13
diff --git a/block/vvfat.c b/block/vvfat.c
14
diff --git a/block/rbd.c b/block/rbd.c
14
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
15
--- a/block/vvfat.c
16
--- a/block/rbd.c
16
+++ b/block/vvfat.c
17
+++ b/block/rbd.c
17
@@ -XXX,XX +XXX,XX @@ static int commit_one_file(BDRVVVFATState* s,
18
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags,
18
uint32_t first_cluster = c;
19
mapping_t* mapping = find_mapping_for_cluster(s, c);
20
uint32_t size = filesize_of_direntry(direntry);
21
- char* cluster = g_malloc(s->cluster_size);
22
+ char *cluster;
23
uint32_t i;
24
int fd = 0;
25
26
@@ -XXX,XX +XXX,XX @@ static int commit_one_file(BDRVVVFATState* s,
27
if (fd < 0) {
28
fprintf(stderr, "Could not open %s... (%s, %d)\n", mapping->path,
29
strerror(errno), errno);
30
- g_free(cluster);
31
return fd;
32
}
33
if (offset > 0) {
34
if (lseek(fd, offset, SEEK_SET) != offset) {
35
qemu_close(fd);
36
- g_free(cluster);
37
return -3;
38
}
19
}
39
}
20
}
40
21
41
+ cluster = g_malloc(s->cluster_size);
22
+ /* When extending regular files, we get zeros from the OS */
23
+ bs->supported_truncate_flags = BDRV_REQ_ZERO_WRITE;
42
+
24
+
43
while (offset < size) {
25
r = 0;
44
uint32_t c1;
26
goto out;
45
int rest_size = (size - offset > s->cluster_size ?
27
46
--
28
--
47
2.19.1
29
2.25.3
48
30
49
31
diff view generated by jsdifflib
New patch
1
From: Eric Blake <eblake@redhat.com>
1
2
3
Our .bdrv_has_zero_init_truncate always returns 1 because sheepdog
4
always 0-fills; we can use that same knowledge to implement
5
BDRV_REQ_ZERO_WRITE by ignoring it.
6
7
Signed-off-by: Eric Blake <eblake@redhat.com>
8
Message-Id: <20200428202905.770727-6-eblake@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
11
block/sheepdog.c | 1 +
12
1 file changed, 1 insertion(+)
13
14
diff --git a/block/sheepdog.c b/block/sheepdog.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/block/sheepdog.c
17
+++ b/block/sheepdog.c
18
@@ -XXX,XX +XXX,XX @@ static int sd_open(BlockDriverState *bs, QDict *options, int flags,
19
memcpy(&s->inode, buf, sizeof(s->inode));
20
21
bs->total_sectors = s->inode.vdi_size / BDRV_SECTOR_SIZE;
22
+ bs->supported_truncate_flags = BDRV_REQ_ZERO_WRITE;
23
pstrcpy(s->name, sizeof(s->name), vdi);
24
qemu_co_mutex_init(&s->lock);
25
qemu_co_mutex_init(&s->queue_lock);
26
--
27
2.25.3
28
29
diff view generated by jsdifflib
New patch
1
From: Eric Blake <eblake@redhat.com>
1
2
3
Our .bdrv_has_zero_init_truncate can detect when the remote side
4
always zero fills; we can reuse that same knowledge to implement
5
BDRV_REQ_ZERO_WRITE by ignoring it when the server gives it to us for
6
free.
7
8
Signed-off-by: Eric Blake <eblake@redhat.com>
9
Message-Id: <20200428202905.770727-7-eblake@redhat.com>
10
Reviewed-by: Richard W.M. Jones <rjones@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
---
13
block/ssh.c | 4 ++++
14
1 file changed, 4 insertions(+)
15
16
diff --git a/block/ssh.c b/block/ssh.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/block/ssh.c
19
+++ b/block/ssh.c
20
@@ -XXX,XX +XXX,XX @@ static int ssh_file_open(BlockDriverState *bs, QDict *options, int bdrv_flags,
21
/* Go non-blocking. */
22
ssh_set_blocking(s->session, 0);
23
24
+ if (s->attrs->type == SSH_FILEXFER_TYPE_REGULAR) {
25
+ bs->supported_truncate_flags = BDRV_REQ_ZERO_WRITE;
26
+ }
27
+
28
qapi_free_BlockdevOptionsSsh(opts);
29
30
return 0;
31
--
32
2.25.3
33
34
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
1
From: Eric Blake <eblake@redhat.com>
2
2
3
Although off_t permits up to 63 bits (8EB) of file offsets, in
3
The parallels driver tries to use truncation for image growth, but can
4
practice, we're going to hit other limits first. Document some
4
only do so when reads are guaranteed as zero. Now that we have a way
5
of those limits in the qcow2 spec (some are inherent, others are
5
to request zero contents from truncation, we can defer the decision to
6
implementation choices of qemu), and how choice of cluster size
6
actual allocation attempts rather than up front, reducing the number
7
can influence some of the limits.
7
of places that still use bdrv_has_zero_init_truncate.
8
9
While we cannot map any uncompressed virtual cluster to any
10
address higher than 64 PB (56 bits) (due to the current L1/L2
11
field encoding stopping at bit 55), qemu's cap of 8M for the
12
refcount table can still access larger host addresses for some
13
combinations of large clusters and small refcount_order. For
14
comparison, ext4 with 4k blocks caps files at 16PB.
15
16
Another interesting limit: for compressed clusters, the L2 layout
17
requires an ever-smaller maximum host offset as cluster size gets
18
larger, down to a 512 TB maximum with 2M clusters. In particular,
19
note that with a cluster size of 8k or smaller, the L2 entry for
20
a compressed cluster could technically point beyond the 64PB mark,
21
but when you consider that with 8k clusters and refcount_order = 0,
22
you cannot access beyond 512T without exceeding qemu's limit of an
23
8M cap on the refcount table, it is unlikely that any image in the
24
wild has attempted to do so. To be safe, let's document that bits
25
beyond 55 in a compressed cluster must be 0.
26
8
27
Signed-off-by: Eric Blake <eblake@redhat.com>
9
Signed-off-by: Eric Blake <eblake@redhat.com>
10
Message-Id: <20200428202905.770727-8-eblake@redhat.com>
11
Reviewed-by: Denis V. Lunev <den@openvz.org>
28
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
29
---
13
---
30
docs/interop/qcow2.txt | 38 ++++++++++++++++++++++++++++++++++++--
14
block/parallels.c | 25 ++++++++++++++++---------
31
1 file changed, 36 insertions(+), 2 deletions(-)
15
1 file changed, 16 insertions(+), 9 deletions(-)
32
16
33
diff --git a/docs/interop/qcow2.txt b/docs/interop/qcow2.txt
17
diff --git a/block/parallels.c b/block/parallels.c
34
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
35
--- a/docs/interop/qcow2.txt
19
--- a/block/parallels.c
36
+++ b/docs/interop/qcow2.txt
20
+++ b/block/parallels.c
37
@@ -XXX,XX +XXX,XX @@ The first cluster of a qcow2 image contains the file header:
21
@@ -XXX,XX +XXX,XX @@ static int64_t block_status(BDRVParallelsState *s, int64_t sector_num,
38
with larger cluster sizes.
22
static int64_t allocate_clusters(BlockDriverState *bs, int64_t sector_num,
39
23
int nb_sectors, int *pnum)
40
24 - 31: size
24
{
41
- Virtual disk size in bytes
25
- int ret;
42
+ Virtual disk size in bytes.
26
+ int ret = 0;
43
+
27
BDRVParallelsState *s = bs->opaque;
44
+ Note: qemu has an implementation limit of 32 MB as
28
int64_t pos, space, idx, to_allocate, i, len;
45
+ the maximum L1 table size. With a 2 MB cluster
29
46
+ size, it is unable to populate a virtual cluster
30
@@ -XXX,XX +XXX,XX @@ static int64_t allocate_clusters(BlockDriverState *bs, int64_t sector_num,
47
+ beyond 2 EB (61 bits); with a 512 byte cluster
31
}
48
+ size, it is unable to populate a virtual size
32
if (s->data_end + space > (len >> BDRV_SECTOR_BITS)) {
49
+ larger than 128 GB (37 bits). Meanwhile, L1/L2
33
space += s->prealloc_size;
50
+ table layouts limit an image to no more than 64 PB
34
+ /*
51
+ (56 bits) of populated clusters, and an image may
35
+ * We require the expanded size to read back as zero. If the
52
+ hit other limits first (such as a file system's
36
+ * user permitted truncation, we try that; but if it fails, we
53
+ maximum size).
37
+ * force the safer-but-slower fallocate.
54
38
+ */
55
32 - 35: crypt_method
39
+ if (s->prealloc_mode == PRL_PREALLOC_MODE_TRUNCATE) {
56
0 for no encryption
40
+ ret = bdrv_truncate(bs->file,
57
@@ -XXX,XX +XXX,XX @@ in the image file.
41
+ (s->data_end + space) << BDRV_SECTOR_BITS,
58
It contains pointers to the second level structures which are called refcount
42
+ false, PREALLOC_MODE_OFF, BDRV_REQ_ZERO_WRITE,
59
blocks and are exactly one cluster in size.
43
+ NULL);
60
44
+ if (ret == -ENOTSUP) {
61
+Although a large enough refcount table can reserve clusters past 64 PB
45
+ s->prealloc_mode = PRL_PREALLOC_MODE_FALLOCATE;
62
+(56 bits) (assuming the underlying protocol can even be sized that
46
+ }
63
+large), note that some qcow2 metadata such as L1/L2 tables must point
47
+ }
64
+to clusters prior to that point.
48
if (s->prealloc_mode == PRL_PREALLOC_MODE_FALLOCATE) {
65
+
49
ret = bdrv_pwrite_zeroes(bs->file,
66
+Note: qemu has an implementation limit of 8 MB as the maximum refcount
50
s->data_end << BDRV_SECTOR_BITS,
67
+table size. With a 2 MB cluster size and a default refcount_order of
51
space << BDRV_SECTOR_BITS, 0);
68
+4, it is unable to reference host resources beyond 2 EB (61 bits); in
52
- } else {
69
+the worst case, with a 512 cluster size and refcount_order of 6, it is
53
- ret = bdrv_truncate(bs->file,
70
+unable to access beyond 32 GB (35 bits).
54
- (s->data_end + space) << BDRV_SECTOR_BITS,
71
+
55
- false, PREALLOC_MODE_OFF, 0, NULL);
72
Given an offset into the image file, the refcount of its cluster can be
56
}
73
obtained as follows:
57
if (ret < 0) {
74
58
return ret;
75
@@ -XXX,XX +XXX,XX @@ The L1 table has a variable size (stored in the header) and may use multiple
59
@@ -XXX,XX +XXX,XX @@ static int parallels_open(BlockDriverState *bs, QDict *options, int flags,
76
clusters, however it must be contiguous in the image file. L2 tables are
60
qemu_opt_get_size_del(opts, PARALLELS_OPT_PREALLOC_SIZE, 0);
77
exactly one cluster in size.
61
s->prealloc_size = MAX(s->tracks, s->prealloc_size >> BDRV_SECTOR_BITS);
78
62
buf = qemu_opt_get_del(opts, PARALLELS_OPT_PREALLOC_MODE);
79
+The L1 and L2 tables have implications on the maximum virtual file
63
+ /* prealloc_mode can be downgraded later during allocate_clusters */
80
+size; for a given L1 table size, a larger cluster size is required for
64
s->prealloc_mode = qapi_enum_parse(&prealloc_mode_lookup, buf,
81
+the guest to have access to more space. Furthermore, a virtual
65
PRL_PREALLOC_MODE_FALLOCATE,
82
+cluster must currently map to a host offset below 64 PB (56 bits)
66
&local_err);
83
+(although this limit could be relaxed by putting reserved bits into
67
@@ -XXX,XX +XXX,XX @@ static int parallels_open(BlockDriverState *bs, QDict *options, int flags,
84
+use). Additionally, as cluster size increases, the maximum host
68
goto fail_options;
85
+offset for a compressed cluster is reduced (a 2M cluster size requires
69
}
86
+compressed clusters to reside below 512 TB (49 bits), and this limit
70
87
+cannot be relaxed without an incompatible layout change).
71
- if (!bdrv_has_zero_init_truncate(bs->file->bs)) {
88
+
72
- s->prealloc_mode = PRL_PREALLOC_MODE_FALLOCATE;
89
Given an offset into the virtual disk, the offset into the image file can be
73
- }
90
obtained as follows:
74
-
91
75
if ((flags & BDRV_O_RDWR) && !(flags & BDRV_O_INACTIVE)) {
92
@@ -XXX,XX +XXX,XX @@ Standard Cluster Descriptor:
76
s->header->inuse = cpu_to_le32(HEADER_INUSE_MAGIC);
93
Compressed Clusters Descriptor (x = 62 - (cluster_bits - 8)):
77
ret = parallels_update_header(bs);
94
95
Bit 0 - x-1: Host cluster offset. This is usually _not_ aligned to a
96
- cluster or sector boundary!
97
+ cluster or sector boundary! If cluster_bits is
98
+ small enough that this field includes bits beyond
99
+ 55, those upper bits must be set to 0.
100
101
x - 61: Number of additional 512-byte sectors used for the
102
compressed data, beyond the sector containing the offset
103
--
78
--
104
2.19.1
79
2.25.3
105
80
106
81
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Eric Blake <eblake@redhat.com>
2
2
3
bdrv_reopen_multiple() does not invoke bdrv_reopen_abort() for the
3
The vhdx driver uses truncation for image growth, with a special case
4
element of the reopen queue for which bdrv_reopen_prepare() failed,
4
for blocks that already read as zero but which are only being
5
because it assumes that the prepare function will have rolled back all
5
partially written. But with a bit of rearranging, it's just as easy
6
changes already.
6
to defer the decision on whether truncation resulted in zeroes to the
7
actual allocation attempt, reducing the number of places that still
8
use bdrv_has_zero_init_truncate.
7
9
8
However, bdrv_reopen_prepare() does not do this in every case: It may
10
Signed-off-by: Eric Blake <eblake@redhat.com>
9
notice an error after BlockDriver.bdrv_reopen_prepare() succeeded, and
11
Message-Id: <20200428202905.770727-9-eblake@redhat.com>
10
it will not invoke BlockDriver.bdrv_reopen_abort() then; and neither
11
will bdrv_reopen_multiple(), as explained above.
12
13
This is wrong because we must always call .bdrv_reopen_commit() or
14
.bdrv_reopen_abort() after .bdrv_reopen_prepare() has succeeded.
15
Otherwise, the block driver has no chance to undo what it has done in
16
its implementation of .bdrv_reopen_prepare().
17
18
To fix this, bdrv_reopen_prepare() has to call .bdrv_reopen_abort() if
19
it wants to return an error after .bdrv_reopen_prepare() has succeeded.
20
21
Signed-off-by: Max Reitz <mreitz@redhat.com>
22
Reviewed-by: Alberto Garcia <berto@igalia.com>
23
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
24
---
13
---
25
block.c | 12 ++++++++++++
14
block/vhdx.c | 89 ++++++++++++++++++++++++++++++----------------------
26
1 file changed, 12 insertions(+)
15
1 file changed, 51 insertions(+), 38 deletions(-)
27
16
28
diff --git a/block.c b/block.c
17
diff --git a/block/vhdx.c b/block/vhdx.c
29
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
30
--- a/block.c
19
--- a/block/vhdx.c
31
+++ b/block.c
20
+++ b/block/vhdx.c
32
@@ -XXX,XX +XXX,XX @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue,
21
@@ -XXX,XX +XXX,XX @@ exit:
33
QDict *orig_reopen_opts;
22
/*
34
char *discard = NULL;
23
* Allocate a new payload block at the end of the file.
35
bool read_only;
24
*
36
+ bool drv_prepared = false;
25
- * Allocation will happen at 1MB alignment inside the file
37
26
+ * Allocation will happen at 1MB alignment inside the file.
38
assert(reopen_state != NULL);
27
+ *
39
assert(reopen_state->bs->drv != NULL);
28
+ * If @need_zero is set on entry but not cleared on return, then truncation
40
@@ -XXX,XX +XXX,XX @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue,
29
+ * could not guarantee that the new portion reads as zero, and the caller
41
goto error;
30
+ * will take care of it instead.
31
*
32
* Returns the file offset start of the new payload block
33
*/
34
static int vhdx_allocate_block(BlockDriverState *bs, BDRVVHDXState *s,
35
- uint64_t *new_offset)
36
+ uint64_t *new_offset, bool *need_zero)
37
{
38
int64_t current_len;
39
40
@@ -XXX,XX +XXX,XX @@ static int vhdx_allocate_block(BlockDriverState *bs, BDRVVHDXState *s,
41
return -EINVAL;
42
}
42
}
43
43
44
+ drv_prepared = true;
44
+ if (*need_zero) {
45
+ int ret;
45
+
46
+
46
/* Options that are not handled are only okay if they are unchanged
47
+ ret = bdrv_truncate(bs->file, *new_offset + s->block_size, false,
47
* compared to the old state. It is expected that some options are only
48
+ PREALLOC_MODE_OFF, BDRV_REQ_ZERO_WRITE, NULL);
48
* used for the initial open, but not reopen (e.g. filename) */
49
+ if (ret != -ENOTSUP) {
49
@@ -XXX,XX +XXX,XX @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue,
50
+ *need_zero = false;
50
reopen_state->options = qobject_ref(orig_reopen_opts);
51
+ return ret;
51
52
error:
53
+ if (ret < 0 && drv_prepared) {
54
+ /* drv->bdrv_reopen_prepare() has succeeded, so we need to
55
+ * call drv->bdrv_reopen_abort() before signaling an error
56
+ * (bdrv_reopen_multiple() will not call bdrv_reopen_abort()
57
+ * when the respective bdrv_reopen_prepare() has failed) */
58
+ if (drv->bdrv_reopen_abort) {
59
+ drv->bdrv_reopen_abort(reopen_state);
60
+ }
52
+ }
61
+ }
53
+ }
62
qemu_opts_del(opts);
54
+
63
qobject_unref(orig_reopen_opts);
55
return bdrv_truncate(bs->file, *new_offset + s->block_size, false,
64
g_free(discard);
56
PREALLOC_MODE_OFF, 0, NULL);
57
}
58
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int vhdx_co_writev(BlockDriverState *bs, int64_t sector_num,
59
/* in this case, we need to preserve zero writes for
60
* data that is not part of this write, so we must pad
61
* the rest of the buffer to zeroes */
62
-
63
- /* if we are on a posix system with ftruncate() that extends
64
- * a file, then it is zero-filled for us. On Win32, the raw
65
- * layer uses SetFilePointer and SetFileEnd, which does not
66
- * zero fill AFAIK */
67
-
68
- /* Queue another write of zero buffers if the underlying file
69
- * does not zero-fill on file extension */
70
-
71
- if (bdrv_has_zero_init_truncate(bs->file->bs) == 0) {
72
- use_zero_buffers = true;
73
-
74
+ use_zero_buffers = true;
75
+ /* fall through */
76
+ case PAYLOAD_BLOCK_NOT_PRESENT: /* fall through */
77
+ case PAYLOAD_BLOCK_UNMAPPED:
78
+ case PAYLOAD_BLOCK_UNMAPPED_v095:
79
+ case PAYLOAD_BLOCK_UNDEFINED:
80
+ bat_prior_offset = sinfo.file_offset;
81
+ ret = vhdx_allocate_block(bs, s, &sinfo.file_offset,
82
+ &use_zero_buffers);
83
+ if (ret < 0) {
84
+ goto exit;
85
+ }
86
+ /*
87
+ * once we support differencing files, this may also be
88
+ * partially present
89
+ */
90
+ /* update block state to the newly specified state */
91
+ vhdx_update_bat_table_entry(bs, s, &sinfo, &bat_entry,
92
+ &bat_entry_offset,
93
+ PAYLOAD_BLOCK_FULLY_PRESENT);
94
+ bat_update = true;
95
+ /*
96
+ * Since we just allocated a block, file_offset is the
97
+ * beginning of the payload block. It needs to be the
98
+ * write address, which includes the offset into the
99
+ * block, unless the entire block needs to read as
100
+ * zeroes but truncation was not able to provide them,
101
+ * in which case we need to fill in the rest.
102
+ */
103
+ if (!use_zero_buffers) {
104
+ sinfo.file_offset += sinfo.block_offset;
105
+ } else {
106
/* zero fill the front, if any */
107
if (sinfo.block_offset) {
108
iov1.iov_len = sinfo.block_offset;
109
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int vhdx_co_writev(BlockDriverState *bs, int64_t sector_num,
110
}
111
112
/* our actual data */
113
- qemu_iovec_concat(&hd_qiov, qiov, bytes_done,
114
+ qemu_iovec_concat(&hd_qiov, qiov, bytes_done,
115
sinfo.bytes_avail);
116
117
/* zero fill the back, if any */
118
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int vhdx_co_writev(BlockDriverState *bs, int64_t sector_num,
119
sectors_to_write += iov2.iov_len >> BDRV_SECTOR_BITS;
120
}
121
}
122
- /* fall through */
123
- case PAYLOAD_BLOCK_NOT_PRESENT: /* fall through */
124
- case PAYLOAD_BLOCK_UNMAPPED:
125
- case PAYLOAD_BLOCK_UNMAPPED_v095:
126
- case PAYLOAD_BLOCK_UNDEFINED:
127
- bat_prior_offset = sinfo.file_offset;
128
- ret = vhdx_allocate_block(bs, s, &sinfo.file_offset);
129
- if (ret < 0) {
130
- goto exit;
131
- }
132
- /* once we support differencing files, this may also be
133
- * partially present */
134
- /* update block state to the newly specified state */
135
- vhdx_update_bat_table_entry(bs, s, &sinfo, &bat_entry,
136
- &bat_entry_offset,
137
- PAYLOAD_BLOCK_FULLY_PRESENT);
138
- bat_update = true;
139
- /* since we just allocated a block, file_offset is the
140
- * beginning of the payload block. It needs to be the
141
- * write address, which includes the offset into the block */
142
- if (!use_zero_buffers) {
143
- sinfo.file_offset += sinfo.block_offset;
144
- }
145
+
146
/* fall through */
147
case PAYLOAD_BLOCK_FULLY_PRESENT:
148
/* if the file offset address is in the header zone,
65
--
149
--
66
2.19.1
150
2.25.3
67
151
68
152
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Eric Blake <eblake@redhat.com>
2
2
3
s->locked_shared_perm is the set of bits locked in the file, which is
3
Now that there are no clients of bdrv_has_zero_init_truncate, none of
4
the inverse of the permissions actually shared. So we need to pass them
4
the drivers need to worry about providing it.
5
as they are to raw_apply_lock_bytes() instead of inverting them again.
5
6
6
What's more, this eliminates a source of some confusion: a literal
7
Reported-by: Alberto Garcia <berto@igalia.com>
7
reading of the documentation as written in ceaca56f and implemented in
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
commit 1dcaf527 claims that a driver which returns 0 for
9
Reviewed-by: Alberto Garcia <berto@igalia.com>
9
bdrv_has_zero_init_truncate() must not return 1 for
10
bdrv_has_zero_init(); this condition was violated for parallels, qcow,
11
and sometimes for vdi, although in practice it did not matter since
12
those drivers also lacked .bdrv_co_truncate.
13
14
Signed-off-by: Eric Blake <eblake@redhat.com>
15
Message-Id: <20200428202905.770727-10-eblake@redhat.com>
16
Acked-by: Richard W.M. Jones <rjones@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
17
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
---
18
---
12
block/file-posix.c | 2 +-
19
include/block/block.h | 1 -
13
1 file changed, 1 insertion(+), 1 deletion(-)
20
include/block/block_int.h | 7 -------
14
21
block.c | 21 ---------------------
22
block/file-posix.c | 1 -
23
block/file-win32.c | 1 -
24
block/nfs.c | 1 -
25
block/qcow2.c | 1 -
26
block/qed.c | 1 -
27
block/raw-format.c | 6 ------
28
block/rbd.c | 1 -
29
block/sheepdog.c | 3 ---
30
block/ssh.c | 1 -
31
12 files changed, 45 deletions(-)
32
33
diff --git a/include/block/block.h b/include/block/block.h
34
index XXXXXXX..XXXXXXX 100644
35
--- a/include/block/block.h
36
+++ b/include/block/block.h
37
@@ -XXX,XX +XXX,XX @@ int bdrv_pdiscard(BdrvChild *child, int64_t offset, int64_t bytes);
38
int bdrv_co_pdiscard(BdrvChild *child, int64_t offset, int64_t bytes);
39
int bdrv_has_zero_init_1(BlockDriverState *bs);
40
int bdrv_has_zero_init(BlockDriverState *bs);
41
-int bdrv_has_zero_init_truncate(BlockDriverState *bs);
42
bool bdrv_unallocated_blocks_are_zero(BlockDriverState *bs);
43
bool bdrv_can_write_zeroes_with_unmap(BlockDriverState *bs);
44
int bdrv_block_status(BlockDriverState *bs, int64_t offset,
45
diff --git a/include/block/block_int.h b/include/block/block_int.h
46
index XXXXXXX..XXXXXXX 100644
47
--- a/include/block/block_int.h
48
+++ b/include/block/block_int.h
49
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
50
/*
51
* Returns 1 if newly created images are guaranteed to contain only
52
* zeros, 0 otherwise.
53
- * Must return 0 if .bdrv_has_zero_init_truncate() returns 0.
54
*/
55
int (*bdrv_has_zero_init)(BlockDriverState *bs);
56
57
- /*
58
- * Returns 1 if new areas added by growing the image with
59
- * PREALLOC_MODE_OFF contain only zeros, 0 otherwise.
60
- */
61
- int (*bdrv_has_zero_init_truncate)(BlockDriverState *bs);
62
-
63
/* Remove fd handlers, timers, and other event loop callbacks so the event
64
* loop is no longer in use. Called with no in-flight requests and in
65
* depth-first traversal order with parents before child nodes.
66
diff --git a/block.c b/block.c
67
index XXXXXXX..XXXXXXX 100644
68
--- a/block.c
69
+++ b/block.c
70
@@ -XXX,XX +XXX,XX @@ int bdrv_has_zero_init(BlockDriverState *bs)
71
return 0;
72
}
73
74
-int bdrv_has_zero_init_truncate(BlockDriverState *bs)
75
-{
76
- if (!bs->drv) {
77
- return 0;
78
- }
79
-
80
- if (bs->backing) {
81
- /* Depends on the backing image length, but better safe than sorry */
82
- return 0;
83
- }
84
- if (bs->drv->bdrv_has_zero_init_truncate) {
85
- return bs->drv->bdrv_has_zero_init_truncate(bs);
86
- }
87
- if (bs->file && bs->drv->is_filter) {
88
- return bdrv_has_zero_init_truncate(bs->file->bs);
89
- }
90
-
91
- /* safe default */
92
- return 0;
93
-}
94
-
95
bool bdrv_unallocated_blocks_are_zero(BlockDriverState *bs)
96
{
97
BlockDriverInfo bdi;
15
diff --git a/block/file-posix.c b/block/file-posix.c
98
diff --git a/block/file-posix.c b/block/file-posix.c
16
index XXXXXXX..XXXXXXX 100644
99
index XXXXXXX..XXXXXXX 100644
17
--- a/block/file-posix.c
100
--- a/block/file-posix.c
18
+++ b/block/file-posix.c
101
+++ b/block/file-posix.c
19
@@ -XXX,XX +XXX,XX @@ static void raw_reopen_commit(BDRVReopenState *state)
102
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_file = {
20
103
.bdrv_co_create = raw_co_create,
21
/* Copy locks to the new fd before closing the old one. */
104
.bdrv_co_create_opts = raw_co_create_opts,
22
raw_apply_lock_bytes(NULL, rs->fd, s->locked_perm,
105
.bdrv_has_zero_init = bdrv_has_zero_init_1,
23
- ~s->locked_shared_perm, false, &local_err);
106
- .bdrv_has_zero_init_truncate = bdrv_has_zero_init_1,
24
+ s->locked_shared_perm, false, &local_err);
107
.bdrv_co_block_status = raw_co_block_status,
25
if (local_err) {
108
.bdrv_co_invalidate_cache = raw_co_invalidate_cache,
26
/* shouldn't fail in a sane host, but report it just in case. */
109
.bdrv_co_pwrite_zeroes = raw_co_pwrite_zeroes,
27
error_report_err(local_err);
110
diff --git a/block/file-win32.c b/block/file-win32.c
111
index XXXXXXX..XXXXXXX 100644
112
--- a/block/file-win32.c
113
+++ b/block/file-win32.c
114
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_file = {
115
.bdrv_close = raw_close,
116
.bdrv_co_create_opts = raw_co_create_opts,
117
.bdrv_has_zero_init = bdrv_has_zero_init_1,
118
- .bdrv_has_zero_init_truncate = bdrv_has_zero_init_1,
119
120
.bdrv_aio_preadv = raw_aio_preadv,
121
.bdrv_aio_pwritev = raw_aio_pwritev,
122
diff --git a/block/nfs.c b/block/nfs.c
123
index XXXXXXX..XXXXXXX 100644
124
--- a/block/nfs.c
125
+++ b/block/nfs.c
126
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_nfs = {
127
.create_opts = &nfs_create_opts,
128
129
.bdrv_has_zero_init = nfs_has_zero_init,
130
- .bdrv_has_zero_init_truncate = nfs_has_zero_init,
131
.bdrv_get_allocated_file_size = nfs_get_allocated_file_size,
132
.bdrv_co_truncate = nfs_file_co_truncate,
133
134
diff --git a/block/qcow2.c b/block/qcow2.c
135
index XXXXXXX..XXXXXXX 100644
136
--- a/block/qcow2.c
137
+++ b/block/qcow2.c
138
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_qcow2 = {
139
.bdrv_co_create_opts = qcow2_co_create_opts,
140
.bdrv_co_create = qcow2_co_create,
141
.bdrv_has_zero_init = qcow2_has_zero_init,
142
- .bdrv_has_zero_init_truncate = bdrv_has_zero_init_1,
143
.bdrv_co_block_status = qcow2_co_block_status,
144
145
.bdrv_co_preadv_part = qcow2_co_preadv_part,
146
diff --git a/block/qed.c b/block/qed.c
147
index XXXXXXX..XXXXXXX 100644
148
--- a/block/qed.c
149
+++ b/block/qed.c
150
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_qed = {
151
.bdrv_co_create = bdrv_qed_co_create,
152
.bdrv_co_create_opts = bdrv_qed_co_create_opts,
153
.bdrv_has_zero_init = bdrv_has_zero_init_1,
154
- .bdrv_has_zero_init_truncate = bdrv_has_zero_init_1,
155
.bdrv_co_block_status = bdrv_qed_co_block_status,
156
.bdrv_co_readv = bdrv_qed_co_readv,
157
.bdrv_co_writev = bdrv_qed_co_writev,
158
diff --git a/block/raw-format.c b/block/raw-format.c
159
index XXXXXXX..XXXXXXX 100644
160
--- a/block/raw-format.c
161
+++ b/block/raw-format.c
162
@@ -XXX,XX +XXX,XX @@ static int raw_has_zero_init(BlockDriverState *bs)
163
return bdrv_has_zero_init(bs->file->bs);
164
}
165
166
-static int raw_has_zero_init_truncate(BlockDriverState *bs)
167
-{
168
- return bdrv_has_zero_init_truncate(bs->file->bs);
169
-}
170
-
171
static int coroutine_fn raw_co_create_opts(BlockDriver *drv,
172
const char *filename,
173
QemuOpts *opts,
174
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_raw = {
175
.bdrv_co_ioctl = &raw_co_ioctl,
176
.create_opts = &raw_create_opts,
177
.bdrv_has_zero_init = &raw_has_zero_init,
178
- .bdrv_has_zero_init_truncate = &raw_has_zero_init_truncate,
179
.strong_runtime_opts = raw_strong_runtime_opts,
180
.mutable_opts = mutable_opts,
181
};
182
diff --git a/block/rbd.c b/block/rbd.c
183
index XXXXXXX..XXXXXXX 100644
184
--- a/block/rbd.c
185
+++ b/block/rbd.c
186
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_rbd = {
187
.bdrv_co_create = qemu_rbd_co_create,
188
.bdrv_co_create_opts = qemu_rbd_co_create_opts,
189
.bdrv_has_zero_init = bdrv_has_zero_init_1,
190
- .bdrv_has_zero_init_truncate = bdrv_has_zero_init_1,
191
.bdrv_get_info = qemu_rbd_getinfo,
192
.create_opts = &qemu_rbd_create_opts,
193
.bdrv_getlength = qemu_rbd_getlength,
194
diff --git a/block/sheepdog.c b/block/sheepdog.c
195
index XXXXXXX..XXXXXXX 100644
196
--- a/block/sheepdog.c
197
+++ b/block/sheepdog.c
198
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_sheepdog = {
199
.bdrv_co_create = sd_co_create,
200
.bdrv_co_create_opts = sd_co_create_opts,
201
.bdrv_has_zero_init = bdrv_has_zero_init_1,
202
- .bdrv_has_zero_init_truncate = bdrv_has_zero_init_1,
203
.bdrv_getlength = sd_getlength,
204
.bdrv_get_allocated_file_size = sd_get_allocated_file_size,
205
.bdrv_co_truncate = sd_co_truncate,
206
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_sheepdog_tcp = {
207
.bdrv_co_create = sd_co_create,
208
.bdrv_co_create_opts = sd_co_create_opts,
209
.bdrv_has_zero_init = bdrv_has_zero_init_1,
210
- .bdrv_has_zero_init_truncate = bdrv_has_zero_init_1,
211
.bdrv_getlength = sd_getlength,
212
.bdrv_get_allocated_file_size = sd_get_allocated_file_size,
213
.bdrv_co_truncate = sd_co_truncate,
214
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_sheepdog_unix = {
215
.bdrv_co_create = sd_co_create,
216
.bdrv_co_create_opts = sd_co_create_opts,
217
.bdrv_has_zero_init = bdrv_has_zero_init_1,
218
- .bdrv_has_zero_init_truncate = bdrv_has_zero_init_1,
219
.bdrv_getlength = sd_getlength,
220
.bdrv_get_allocated_file_size = sd_get_allocated_file_size,
221
.bdrv_co_truncate = sd_co_truncate,
222
diff --git a/block/ssh.c b/block/ssh.c
223
index XXXXXXX..XXXXXXX 100644
224
--- a/block/ssh.c
225
+++ b/block/ssh.c
226
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_ssh = {
227
.bdrv_co_create_opts = ssh_co_create_opts,
228
.bdrv_close = ssh_close,
229
.bdrv_has_zero_init = ssh_has_zero_init,
230
- .bdrv_has_zero_init_truncate = ssh_has_zero_init,
231
.bdrv_co_readv = ssh_co_readv,
232
.bdrv_co_writev = ssh_co_writev,
233
.bdrv_getlength = ssh_getlength,
28
--
234
--
29
2.19.1
235
2.25.3
30
236
31
237
diff view generated by jsdifflib