1
The following changes since commit 63f495beb4007de5444614125fd6fd178ca6e2b1:
1
The following changes since commit 16aaacb307ed607b9780c12702c44f0fe52edc7e:
2
2
3
Merge remote-tracking branch 'remotes/kraxel/tags/pull-cve-2017-2620-20170224-1' into staging (2017-02-24 13:55:26 +0000)
3
Merge remote-tracking branch 'remotes/cohuck/tags/s390x-20200430' into staging (2020-04-30 14:00:36 +0100)
4
4
5
are available in the git repository at:
5
are available in the Git repository at:
6
7
6
8
git://repo.or.cz/qemu/kevin.git tags/for-upstream
7
git://repo.or.cz/qemu/kevin.git tags/for-upstream
9
8
10
for you to fetch changes up to d185cf0ec64cd183218ca7e0810d9130c96ebebc:
9
for you to fetch changes up to eaae29ef89d498d0eac553c77b554f310a47f809:
11
10
12
tests: Use opened block node for block job tests (2017-02-24 16:09:23 +0100)
11
qemu-storage-daemon: Fix non-string --object properties (2020-04-30 17:51:07 +0200)
13
12
14
----------------------------------------------------------------
13
----------------------------------------------------------------
15
Block layer patches
14
Block layer patches:
15
16
- Fix resize (extending) of short overlays
17
- nvme: introduce PMR support from NVMe 1.4 spec
18
- qemu-storage-daemon: Fix non-string --object properties
16
19
17
----------------------------------------------------------------
20
----------------------------------------------------------------
18
Jeff Cody (3):
21
Alberto Garcia (1):
19
qemu-iotests: Test 137 only supports 'file' protocol
22
qcow2: Add incompatibility note between backing files and raw external data files
20
qemu-iotests: add ability to exclude certain protocols from tests
21
qemu-iotests: redirect nbd server stdout to /dev/null
22
23
23
John Snow (1):
24
Andrzej Jakowski (1):
24
iotests: Fix another race in 030
25
nvme: introduce PMR support from NVMe 1.4 spec
25
26
26
Kevin Wolf (11):
27
Kevin Wolf (12):
27
blockdev: Use BlockBackend to resize in qmp_block_resize()
28
block: Add flags to BlockDriver.bdrv_co_truncate()
28
qcow2: Use BB for resizing in qcow2_amend_options()
29
block: Add flags to bdrv(_co)_truncate()
29
mirror: Resize active commit base in mirror_run()
30
block-backend: Add flags to blk_truncate()
30
block: Pass BdrvChild to bdrv_truncate()
31
qcow2: Support BDRV_REQ_ZERO_WRITE for truncate
31
block: Attach bs->file only during .bdrv_open()
32
raw-format: Support BDRV_REQ_ZERO_WRITE for truncate
32
block: Factor out bdrv_open_child_bs()
33
file-posix: Support BDRV_REQ_ZERO_WRITE for truncate
33
block: Use BlockBackend for image probing
34
block: truncate: Don't make backing file data visible
34
block: Factor out bdrv_open_driver()
35
iotests: Filter testfiles out in filter_img_info()
35
block: Add bdrv_new_open_driver()
36
iotests: Test committing to short backing file
36
vvfat: Use opened node as backing file
37
qcow2: Forward ZERO_WRITE flag for full preallocation
37
tests: Use opened block node for block job tests
38
qom: Factor out user_creatable_add_dict()
39
qemu-storage-daemon: Fix non-string --object properties
38
40
39
Nir Soffer (4):
41
Paolo Bonzini (1):
40
qemu-img: Do not truncate before preallocation
42
qemu-iotests: allow qcow2 external discarded clusters to contain stale data
41
qemu-img: Add tests for raw image preallocation
42
qemu-img: Truncate before full preallocation
43
qemu-img: Improve documentation for PREALLOC_MODE_FALLOC
44
43
45
block.c | 265 +++++++++++++++++++++++++++---------------
44
docs/interop/qcow2.txt | 3 +
46
block/blkdebug.c | 2 +-
45
hw/block/nvme.h | 2 +
47
block/block-backend.c | 2 +-
46
include/block/block.h | 5 +-
48
block/bochs.c | 6 +
47
include/block/block_int.h | 10 +-
49
block/cloop.c | 6 +
48
include/block/nvme.h | 172 ++++++++++++++++++++++++++
50
block/crypto.c | 8 +-
49
include/qom/object_interfaces.h | 16 +++
51
block/dmg.c | 6 +
50
include/sysemu/block-backend.h | 2 +-
52
block/file-posix.c | 28 +++--
51
block.c | 3 +-
53
block/mirror.c | 50 ++++----
52
block/block-backend.c | 4 +-
54
block/parallels.c | 14 ++-
53
block/commit.c | 4 +-
55
block/qcow.c | 10 +-
54
block/crypto.c | 7 +-
56
block/qcow2-refcount.c | 2 +-
55
block/file-posix.c | 6 +-
57
block/qcow2.c | 28 ++++-
56
block/file-win32.c | 2 +-
58
block/qed.c | 18 ++-
57
block/gluster.c | 1 +
59
block/raw-format.c | 8 +-
58
block/io.c | 43 ++++++-
60
block/replication.c | 6 +
59
block/iscsi.c | 2 +-
61
block/vdi.c | 6 +
60
block/mirror.c | 2 +-
62
block/vhdx-log.c | 2 +-
61
block/nfs.c | 3 +-
63
block/vhdx.c | 8 +-
62
block/parallels.c | 6 +-
64
block/vmdk.c | 6 +
63
block/qcow.c | 4 +-
65
block/vpc.c | 6 +
64
block/qcow2-cluster.c | 2 +-
66
block/vvfat.c | 10 +-
65
block/qcow2-refcount.c | 2 +-
67
blockdev.c | 7 +-
66
block/qcow2.c | 73 +++++++++--
68
include/block/block.h | 4 +-
67
block/qed.c | 3 +-
69
tests/qemu-iotests/030 | 5 +-
68
block/raw-format.c | 6 +-
70
tests/qemu-iotests/051.out | 4 +-
69
block/rbd.c | 1 +
71
tests/qemu-iotests/051.pc.out | 4 +-
70
block/sheepdog.c | 4 +-
72
tests/qemu-iotests/137 | 2 +-
71
block/ssh.c | 2 +-
73
tests/qemu-iotests/175 | 61 ++++++++++
72
block/vdi.c | 2 +-
74
tests/qemu-iotests/175.out | 18 +++
73
block/vhdx-log.c | 2 +-
75
tests/qemu-iotests/common.rc | 14 ++-
74
block/vhdx.c | 6 +-
76
tests/qemu-iotests/group | 1 +
75
block/vmdk.c | 8 +-
77
tests/test-blockjob-txn.c | 6 +-
76
block/vpc.c | 2 +-
78
tests/test-blockjob.c | 6 +-
77
blockdev.c | 2 +-
79
34 files changed, 461 insertions(+), 168 deletions(-)
78
hw/block/nvme.c | 109 ++++++++++++++++
80
create mode 100755 tests/qemu-iotests/175
79
qemu-img.c | 2 +-
81
create mode 100644 tests/qemu-iotests/175.out
80
qemu-io-cmds.c | 2 +-
81
qemu-storage-daemon.c | 4 +-
82
qom/object_interfaces.c | 31 +++++
83
qom/qom-qmp-cmds.c | 24 +---
84
tests/test-block-iothread.c | 9 +-
85
tests/qemu-iotests/iotests.py | 5 +-
86
hw/block/Makefile.objs | 2 +-
87
hw/block/trace-events | 4 +
88
tests/qemu-iotests/244 | 10 +-
89
tests/qemu-iotests/244.out | 9 +-
90
tests/qemu-iotests/274 | 155 +++++++++++++++++++++++
91
tests/qemu-iotests/274.out | 268 ++++++++++++++++++++++++++++++++++++++++
92
tests/qemu-iotests/group | 1 +
93
49 files changed, 951 insertions(+), 96 deletions(-)
94
create mode 100755 tests/qemu-iotests/274
95
create mode 100644 tests/qemu-iotests/274.out
82
96
97
diff view generated by jsdifflib
Deleted patch
1
From: Jeff Cody <jcody@redhat.com>
2
1
3
Since test 137 make uses of qcow2.py, only local files are supported.
4
5
Signed-off-by: Jeff Cody <jcody@redhat.com>
6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
---
8
tests/qemu-iotests/137 | 2 +-
9
1 file changed, 1 insertion(+), 1 deletion(-)
10
11
diff --git a/tests/qemu-iotests/137 b/tests/qemu-iotests/137
12
index XXXXXXX..XXXXXXX 100755
13
--- a/tests/qemu-iotests/137
14
+++ b/tests/qemu-iotests/137
15
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
16
. ./common.qemu
17
18
_supported_fmt qcow2
19
-_supported_proto generic
20
+_supported_proto file
21
_supported_os Linux
22
23
24
--
25
1.8.3.1
26
27
diff view generated by jsdifflib
1
From: Jeff Cody <jcody@redhat.com>
1
From: Alberto Garcia <berto@igalia.com>
2
2
3
Some iotests (e.g. 174) try to filter the output of _make_test_image by
3
Backing files and raw external data files are mutually exclusive.
4
piping the stdout. Pipe the server stdout to /dev/null, so that filter
4
The documentation of the raw external data bit (in autoclear_features)
5
pipe does not need to wait until process completion.
5
already indicates that, but we should also mention it on the other
6
side.
6
7
7
Signed-off-by: Jeff Cody <jcody@redhat.com>
8
Suggested-by: Eric Blake <eblake@redhat.com>
9
Signed-off-by: Alberto Garcia <berto@igalia.com>
10
Message-Id: <20200410121816.8334-1-berto@igalia.com>
8
Reviewed-by: Eric Blake <eblake@redhat.com>
11
Reviewed-by: Eric Blake <eblake@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
13
---
11
tests/qemu-iotests/common.rc | 2 +-
14
docs/interop/qcow2.txt | 3 +++
12
1 file changed, 1 insertion(+), 1 deletion(-)
15
1 file changed, 3 insertions(+)
13
16
14
diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc
17
diff --git a/docs/interop/qcow2.txt b/docs/interop/qcow2.txt
15
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
16
--- a/tests/qemu-iotests/common.rc
19
--- a/docs/interop/qcow2.txt
17
+++ b/tests/qemu-iotests/common.rc
20
+++ b/docs/interop/qcow2.txt
18
@@ -XXX,XX +XXX,XX @@ _make_test_img()
21
@@ -XXX,XX +XXX,XX @@ The first cluster of a qcow2 image contains the file header:
19
22
is stored (NB: The string is not null terminated). 0 if the
20
# Start an NBD server on the image file, which is what we'll be talking to
23
image doesn't have a backing file.
21
if [ $IMGPROTO = "nbd" ]; then
24
22
- eval "$QEMU_NBD -v -t -b 127.0.0.1 -p 10810 -f $IMGFMT $TEST_IMG_FILE &"
25
+ Note: backing files are incompatible with raw external data
23
+ eval "$QEMU_NBD -v -t -b 127.0.0.1 -p 10810 -f $IMGFMT $TEST_IMG_FILE >/dev/null &"
26
+ files (auto-clear feature bit 1).
24
sleep 1 # FIXME: qemu-nbd needs to be listening before we continue
27
+
25
fi
28
16 - 19: backing_file_size
26
}
29
Length of the backing file name in bytes. Must not be
30
longer than 1023 bytes. Undefined if the image doesn't have
27
--
31
--
28
1.8.3.1
32
2.25.3
29
33
30
34
diff view generated by jsdifflib
1
From: John Snow <jsnow@redhat.com>
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
2
3
We can't rely on a non-paused job to be present and running for us.
3
Test 244 checks the expected behavior of qcow2 external data files
4
Assume that if the job is not present that it completed already.
4
with respect to zero and discarded clusters. Filesystems however
5
are free to ignore discard requests, and this seems to be the
6
case for overlayfs. Relax the tests to skip checks on the
7
external data file for discarded areas, which implies not using
8
qemu-img compare in the data_file_raw=on case.
5
9
6
Signed-off-by: John Snow <jsnow@redhat.com>
10
This fixes docker tests on RHEL8.
7
Reviewed-by: Fam Zheng <famz@redhat.com>
11
12
Cc: Kevin Wolf <kwolf@redhat.com>
13
Cc: qemu-block@nongnu.org
14
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
15
Message-Id: <20200409191006.24429-1-pbonzini@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
16
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
17
---
10
tests/qemu-iotests/030 | 5 ++++-
18
tests/qemu-iotests/244 | 10 ++++++++--
11
1 file changed, 4 insertions(+), 1 deletion(-)
19
tests/qemu-iotests/244.out | 9 ++++++---
20
2 files changed, 14 insertions(+), 5 deletions(-)
12
21
13
diff --git a/tests/qemu-iotests/030 b/tests/qemu-iotests/030
22
diff --git a/tests/qemu-iotests/244 b/tests/qemu-iotests/244
14
index XXXXXXX..XXXXXXX 100755
23
index XXXXXXX..XXXXXXX 100755
15
--- a/tests/qemu-iotests/030
24
--- a/tests/qemu-iotests/244
16
+++ b/tests/qemu-iotests/030
25
+++ b/tests/qemu-iotests/244
17
@@ -XXX,XX +XXX,XX @@ class TestEIO(TestErrors):
26
@@ -XXX,XX +XXX,XX @@ $QEMU_IO -c 'read -P 0 0 1M' \
18
while not completed:
27
echo
19
for event in self.vm.get_qmp_events(wait=True):
28
$QEMU_IO -c 'read -P 0 0 1M' \
20
if event['event'] == 'BLOCK_JOB_ERROR':
29
-c 'read -P 0x11 1M 1M' \
21
+ error = True
30
- -c 'read -P 0 2M 2M' \
22
self.assert_qmp(event, 'data/device', 'drive0')
31
-c 'read -P 0x11 4M 1M' \
23
self.assert_qmp(event, 'data/operation', 'read')
32
-c 'read -P 0 5M 1M' \
24
result = self.vm.qmp('query-block-jobs')
33
-f raw "$TEST_IMG.data" |
25
+ if result == {'return': []}:
34
@@ -XXX,XX +XXX,XX @@ $QEMU_IO -c 'read -P 0 0 1M' \
26
+ # Job finished too quickly
35
-f $IMGFMT "$TEST_IMG" |
27
+ continue
36
_filter_qemu_io
28
self.assert_qmp(result, 'return[0]/paused', False)
37
29
- error = True
38
+# Discarded clusters are only marked as such in the qcow2 metadata, but
30
elif event['event'] == 'BLOCK_JOB_COMPLETED':
39
+# they can contain stale data in the external data file. Instead, zero
31
self.assertTrue(error, 'job completed unexpectedly')
40
+# clusters must be zeroed in the external data file too.
32
self.assert_qmp(event, 'data/type', 'stream')
41
echo
42
-$QEMU_IMG compare "$TEST_IMG" "$TEST_IMG.data"
43
+$QEMU_IO -c 'read -P 0 0 1M' \
44
+ -c 'read -P 0x11 1M 1M' \
45
+ -c 'read -P 0 3M 3M' \
46
+ -f raw "$TEST_IMG".data |
47
+ _filter_qemu_io
48
49
echo -n "qcow2 file size after I/O: "
50
du -b $TEST_IMG | cut -f1
51
diff --git a/tests/qemu-iotests/244.out b/tests/qemu-iotests/244.out
52
index XXXXXXX..XXXXXXX 100644
53
--- a/tests/qemu-iotests/244.out
54
+++ b/tests/qemu-iotests/244.out
55
@@ -XXX,XX +XXX,XX @@ read 1048576/1048576 bytes at offset 0
56
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
57
read 1048576/1048576 bytes at offset 1048576
58
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
59
-read 2097152/2097152 bytes at offset 2097152
60
-2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
61
read 1048576/1048576 bytes at offset 4194304
62
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
63
read 1048576/1048576 bytes at offset 5242880
64
@@ -XXX,XX +XXX,XX @@ read 1048576/1048576 bytes at offset 1048576
65
read 4194304/4194304 bytes at offset 2097152
66
4 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
67
68
-Images are identical.
69
+read 1048576/1048576 bytes at offset 0
70
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
71
+read 1048576/1048576 bytes at offset 1048576
72
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
73
+read 3145728/3145728 bytes at offset 3145728
74
+3 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
75
qcow2 file size after I/O: 327680
76
77
=== bdrv_co_block_status test for file and offset=0 ===
33
--
78
--
34
1.8.3.1
79
2.25.3
35
80
36
81
diff view generated by jsdifflib
1
From: Nir Soffer <nirsof@gmail.com>
1
This adds a new BdrvRequestFlags parameter to the .bdrv_co_truncate()
2
2
driver callbacks, and a supported_truncate_flags field in
3
In a previous commit (qemu-img: Do not truncate before preallocation) we
3
BlockDriverState that allows drivers to advertise support for request
4
moved truncate to the PREALLOC_MODE_OFF branch to avoid slowdown in
4
flags in the context of truncate.
5
posix_fallocate().
5
6
6
For now, we always pass 0 and no drivers declare support for any flag.
7
However this change is not optimal when using PREALLOC_MODE_FULL, since
7
8
knowing the final size from the beginning could allow the file system
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
driver to do less allocations and possibly avoid fragmentation of the
9
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
10
file.
10
Reviewed-by: Alberto Garcia <berto@igalia.com>
11
11
Reviewed-by: Max Reitz <mreitz@redhat.com>
12
Now we truncate also before doing full preallocation.
12
Message-Id: <20200424125448.63318-2-kwolf@redhat.com>
13
14
Signed-off-by: Nir Soffer <nirsof@gmail.com>
15
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
16
---
14
---
17
block/file-posix.c | 12 ++++++++++++
15
include/block/block_int.h | 10 +++++++++-
18
1 file changed, 12 insertions(+)
16
block/crypto.c | 3 ++-
19
17
block/file-posix.c | 2 +-
18
block/file-win32.c | 2 +-
19
block/gluster.c | 1 +
20
block/io.c | 8 +++++++-
21
block/iscsi.c | 2 +-
22
block/nfs.c | 3 ++-
23
block/qcow2.c | 2 +-
24
block/qed.c | 1 +
25
block/raw-format.c | 2 +-
26
block/rbd.c | 1 +
27
block/sheepdog.c | 4 ++--
28
block/ssh.c | 2 +-
29
tests/test-block-iothread.c | 3 ++-
30
15 files changed, 33 insertions(+), 13 deletions(-)
31
32
diff --git a/include/block/block_int.h b/include/block/block_int.h
33
index XXXXXXX..XXXXXXX 100644
34
--- a/include/block/block_int.h
35
+++ b/include/block/block_int.h
36
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
37
*/
38
int coroutine_fn (*bdrv_co_truncate)(BlockDriverState *bs, int64_t offset,
39
bool exact, PreallocMode prealloc,
40
- Error **errp);
41
+ BdrvRequestFlags flags, Error **errp);
42
43
int64_t (*bdrv_getlength)(BlockDriverState *bs);
44
bool has_variable_length;
45
@@ -XXX,XX +XXX,XX @@ struct BlockDriverState {
46
/* Flags honored during pwrite_zeroes (so far: BDRV_REQ_FUA,
47
* BDRV_REQ_MAY_UNMAP, BDRV_REQ_WRITE_UNCHANGED) */
48
unsigned int supported_zero_flags;
49
+ /*
50
+ * Flags honoured during truncate (so far: BDRV_REQ_ZERO_WRITE).
51
+ *
52
+ * If BDRV_REQ_ZERO_WRITE is given, the truncate operation must make sure
53
+ * that any added space reads as all zeros. If this can't be guaranteed,
54
+ * the operation must fail.
55
+ */
56
+ unsigned int supported_truncate_flags;
57
58
/* the following member gives a name to every node on the bs graph. */
59
char node_name[32];
60
diff --git a/block/crypto.c b/block/crypto.c
61
index XXXXXXX..XXXXXXX 100644
62
--- a/block/crypto.c
63
+++ b/block/crypto.c
64
@@ -XXX,XX +XXX,XX @@ static int block_crypto_co_create_generic(BlockDriverState *bs,
65
66
static int coroutine_fn
67
block_crypto_co_truncate(BlockDriverState *bs, int64_t offset, bool exact,
68
- PreallocMode prealloc, Error **errp)
69
+ PreallocMode prealloc, BdrvRequestFlags flags,
70
+ Error **errp)
71
{
72
BlockCrypto *crypto = bs->opaque;
73
uint64_t payload_offset =
20
diff --git a/block/file-posix.c b/block/file-posix.c
74
diff --git a/block/file-posix.c b/block/file-posix.c
21
index XXXXXXX..XXXXXXX 100644
75
index XXXXXXX..XXXXXXX 100644
22
--- a/block/file-posix.c
76
--- a/block/file-posix.c
23
+++ b/block/file-posix.c
77
+++ b/block/file-posix.c
24
@@ -XXX,XX +XXX,XX @@ static int raw_create(const char *filename, QemuOpts *opts, Error **errp)
78
@@ -XXX,XX +XXX,XX @@ raw_regular_truncate(BlockDriverState *bs, int fd, int64_t offset,
25
#endif
79
26
case PREALLOC_MODE_FULL:
80
static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset,
27
{
81
bool exact, PreallocMode prealloc,
28
+ /*
82
- Error **errp)
29
+ * Knowing the final size from the beginning could allow the file
83
+ BdrvRequestFlags flags, Error **errp)
30
+ * system driver to do less allocations and possibly avoid
84
{
31
+ * fragmentation of the file.
85
BDRVRawState *s = bs->opaque;
32
+ */
86
struct stat st;
33
+ if (ftruncate(fd, total_size) != 0) {
87
diff --git a/block/file-win32.c b/block/file-win32.c
34
+ result = -errno;
88
index XXXXXXX..XXXXXXX 100644
35
+ error_setg_errno(errp, -result, "Could not resize file");
89
--- a/block/file-win32.c
36
+ goto out_close;
90
+++ b/block/file-win32.c
91
@@ -XXX,XX +XXX,XX @@ static void raw_close(BlockDriverState *bs)
92
93
static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset,
94
bool exact, PreallocMode prealloc,
95
- Error **errp)
96
+ BdrvRequestFlags flags, Error **errp)
97
{
98
BDRVRawState *s = bs->opaque;
99
LONG low, high;
100
diff --git a/block/gluster.c b/block/gluster.c
101
index XXXXXXX..XXXXXXX 100644
102
--- a/block/gluster.c
103
+++ b/block/gluster.c
104
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qemu_gluster_co_truncate(BlockDriverState *bs,
105
int64_t offset,
106
bool exact,
107
PreallocMode prealloc,
108
+ BdrvRequestFlags flags,
109
Error **errp)
110
{
111
BDRVGlusterState *s = bs->opaque;
112
diff --git a/block/io.c b/block/io.c
113
index XXXXXXX..XXXXXXX 100644
114
--- a/block/io.c
115
+++ b/block/io.c
116
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
117
BlockDriverState *bs = child->bs;
118
BlockDriver *drv = bs->drv;
119
BdrvTrackedRequest req;
120
+ BdrvRequestFlags flags = 0;
121
int64_t old_size, new_bytes;
122
int ret;
123
124
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
125
}
126
127
if (drv->bdrv_co_truncate) {
128
- ret = drv->bdrv_co_truncate(bs, offset, exact, prealloc, errp);
129
+ if (flags & ~bs->supported_truncate_flags) {
130
+ error_setg(errp, "Block driver does not support requested flags");
131
+ ret = -ENOTSUP;
132
+ goto out;
37
+ }
133
+ }
38
+
134
+ ret = drv->bdrv_co_truncate(bs, offset, exact, prealloc, flags, errp);
39
int64_t num = 0, left = total_size;
135
} else if (bs->file && drv->is_filter) {
40
buf = g_malloc0(65536);
136
ret = bdrv_co_truncate(bs->file, offset, exact, prealloc, errp);
41
137
} else {
42
@@ -XXX,XX +XXX,XX @@ static int raw_create(const char *filename, QemuOpts *opts, Error **errp)
138
diff --git a/block/iscsi.c b/block/iscsi.c
43
break;
139
index XXXXXXX..XXXXXXX 100644
44
}
140
--- a/block/iscsi.c
45
141
+++ b/block/iscsi.c
46
+out_close:
142
@@ -XXX,XX +XXX,XX @@ static void iscsi_reopen_commit(BDRVReopenState *reopen_state)
47
if (qemu_close(fd) != 0 && result == 0) {
143
48
result = -errno;
144
static int coroutine_fn iscsi_co_truncate(BlockDriverState *bs, int64_t offset,
49
error_setg_errno(errp, -result, "Could not close the new file");
145
bool exact, PreallocMode prealloc,
146
- Error **errp)
147
+ BdrvRequestFlags flags, Error **errp)
148
{
149
IscsiLun *iscsilun = bs->opaque;
150
int64_t cur_length;
151
diff --git a/block/nfs.c b/block/nfs.c
152
index XXXXXXX..XXXXXXX 100644
153
--- a/block/nfs.c
154
+++ b/block/nfs.c
155
@@ -XXX,XX +XXX,XX @@ static int64_t nfs_get_allocated_file_size(BlockDriverState *bs)
156
157
static int coroutine_fn
158
nfs_file_co_truncate(BlockDriverState *bs, int64_t offset, bool exact,
159
- PreallocMode prealloc, Error **errp)
160
+ PreallocMode prealloc, BdrvRequestFlags flags,
161
+ Error **errp)
162
{
163
NFSClient *client = bs->opaque;
164
int ret;
165
diff --git a/block/qcow2.c b/block/qcow2.c
166
index XXXXXXX..XXXXXXX 100644
167
--- a/block/qcow2.c
168
+++ b/block/qcow2.c
169
@@ -XXX,XX +XXX,XX @@ fail:
170
171
static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
172
bool exact, PreallocMode prealloc,
173
- Error **errp)
174
+ BdrvRequestFlags flags, Error **errp)
175
{
176
BDRVQcow2State *s = bs->opaque;
177
uint64_t old_length;
178
diff --git a/block/qed.c b/block/qed.c
179
index XXXXXXX..XXXXXXX 100644
180
--- a/block/qed.c
181
+++ b/block/qed.c
182
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_qed_co_truncate(BlockDriverState *bs,
183
int64_t offset,
184
bool exact,
185
PreallocMode prealloc,
186
+ BdrvRequestFlags flags,
187
Error **errp)
188
{
189
BDRVQEDState *s = bs->opaque;
190
diff --git a/block/raw-format.c b/block/raw-format.c
191
index XXXXXXX..XXXXXXX 100644
192
--- a/block/raw-format.c
193
+++ b/block/raw-format.c
194
@@ -XXX,XX +XXX,XX @@ static void raw_refresh_limits(BlockDriverState *bs, Error **errp)
195
196
static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset,
197
bool exact, PreallocMode prealloc,
198
- Error **errp)
199
+ BdrvRequestFlags flags, Error **errp)
200
{
201
BDRVRawState *s = bs->opaque;
202
203
diff --git a/block/rbd.c b/block/rbd.c
204
index XXXXXXX..XXXXXXX 100644
205
--- a/block/rbd.c
206
+++ b/block/rbd.c
207
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qemu_rbd_co_truncate(BlockDriverState *bs,
208
int64_t offset,
209
bool exact,
210
PreallocMode prealloc,
211
+ BdrvRequestFlags flags,
212
Error **errp)
213
{
214
int r;
215
diff --git a/block/sheepdog.c b/block/sheepdog.c
216
index XXXXXXX..XXXXXXX 100644
217
--- a/block/sheepdog.c
218
+++ b/block/sheepdog.c
219
@@ -XXX,XX +XXX,XX @@ static int64_t sd_getlength(BlockDriverState *bs)
220
221
static int coroutine_fn sd_co_truncate(BlockDriverState *bs, int64_t offset,
222
bool exact, PreallocMode prealloc,
223
- Error **errp)
224
+ BdrvRequestFlags flags, Error **errp)
225
{
226
BDRVSheepdogState *s = bs->opaque;
227
int ret, fd;
228
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int sd_co_writev(BlockDriverState *bs, int64_t sector_num,
229
230
assert(!flags);
231
if (offset > s->inode.vdi_size) {
232
- ret = sd_co_truncate(bs, offset, false, PREALLOC_MODE_OFF, NULL);
233
+ ret = sd_co_truncate(bs, offset, false, PREALLOC_MODE_OFF, 0, NULL);
234
if (ret < 0) {
235
return ret;
236
}
237
diff --git a/block/ssh.c b/block/ssh.c
238
index XXXXXXX..XXXXXXX 100644
239
--- a/block/ssh.c
240
+++ b/block/ssh.c
241
@@ -XXX,XX +XXX,XX @@ static int64_t ssh_getlength(BlockDriverState *bs)
242
243
static int coroutine_fn ssh_co_truncate(BlockDriverState *bs, int64_t offset,
244
bool exact, PreallocMode prealloc,
245
- Error **errp)
246
+ BdrvRequestFlags flags, Error **errp)
247
{
248
BDRVSSHState *s = bs->opaque;
249
250
diff --git a/tests/test-block-iothread.c b/tests/test-block-iothread.c
251
index XXXXXXX..XXXXXXX 100644
252
--- a/tests/test-block-iothread.c
253
+++ b/tests/test-block-iothread.c
254
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_test_co_pdiscard(BlockDriverState *bs,
255
256
static int coroutine_fn
257
bdrv_test_co_truncate(BlockDriverState *bs, int64_t offset, bool exact,
258
- PreallocMode prealloc, Error **errp)
259
+ PreallocMode prealloc, BdrvRequestFlags flags,
260
+ Error **errp)
261
{
262
return 0;
263
}
50
--
264
--
51
1.8.3.1
265
2.25.3
52
266
53
267
diff view generated by jsdifflib
1
Now that block drivers can support flags for .bdrv_co_truncate, expose
2
the parameter in the node level interfaces bdrv_co_truncate() and
3
bdrv_truncate().
4
1
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
7
Reviewed-by: Alberto Garcia <berto@igalia.com>
2
Reviewed-by: Max Reitz <mreitz@redhat.com>
8
Reviewed-by: Max Reitz <mreitz@redhat.com>
9
Message-Id: <20200424125448.63318-3-kwolf@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
3
---
11
---
4
block.c | 3 ++-
12
include/block/block.h | 5 +++--
5
block/blkdebug.c | 2 +-
13
block/block-backend.c | 2 +-
6
block/block-backend.c | 2 +-
14
block/crypto.c | 2 +-
7
block/crypto.c | 2 +-
15
block/io.c | 12 +++++++-----
8
block/parallels.c | 8 ++++----
16
block/parallels.c | 6 +++---
9
block/qcow.c | 4 ++--
17
block/qcow.c | 4 ++--
10
block/qcow2-refcount.c | 2 +-
18
block/qcow2-refcount.c | 2 +-
11
block/qcow2.c | 4 ++--
19
block/qcow2.c | 15 +++++++++------
12
block/raw-format.c | 2 +-
20
block/raw-format.c | 2 +-
13
block/vhdx-log.c | 2 +-
21
block/vhdx-log.c | 2 +-
14
block/vhdx.c | 2 +-
22
block/vhdx.c | 2 +-
15
include/block/block.h | 2 +-
23
block/vmdk.c | 2 +-
16
12 files changed, 18 insertions(+), 17 deletions(-)
24
tests/test-block-iothread.c | 6 +++---
25
13 files changed, 34 insertions(+), 28 deletions(-)
17
26
18
diff --git a/block.c b/block.c
27
diff --git a/include/block/block.h b/include/block/block.h
19
index XXXXXXX..XXXXXXX 100644
28
index XXXXXXX..XXXXXXX 100644
20
--- a/block.c
29
--- a/include/block/block.h
21
+++ b/block.c
30
+++ b/include/block/block.h
22
@@ -XXX,XX +XXX,XX @@ exit:
31
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs,
23
/**
32
void bdrv_refresh_filename(BlockDriverState *bs);
24
* Truncate file to 'offset' bytes (needed only for file protocols)
33
25
*/
34
int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
26
-int bdrv_truncate(BlockDriverState *bs, int64_t offset)
35
- PreallocMode prealloc, Error **errp);
27
+int bdrv_truncate(BdrvChild *child, int64_t offset)
36
+ PreallocMode prealloc, BdrvRequestFlags flags,
28
{
37
+ Error **errp);
29
+ BlockDriverState *bs = child->bs;
38
int bdrv_truncate(BdrvChild *child, int64_t offset, bool exact,
30
BlockDriver *drv = bs->drv;
39
- PreallocMode prealloc, Error **errp);
31
int ret;
40
+ PreallocMode prealloc, BdrvRequestFlags flags, Error **errp);
32
if (!drv)
41
33
diff --git a/block/blkdebug.c b/block/blkdebug.c
42
int64_t bdrv_nb_sectors(BlockDriverState *bs);
34
index XXXXXXX..XXXXXXX 100644
43
int64_t bdrv_getlength(BlockDriverState *bs);
35
--- a/block/blkdebug.c
36
+++ b/block/blkdebug.c
37
@@ -XXX,XX +XXX,XX @@ static int64_t blkdebug_getlength(BlockDriverState *bs)
38
39
static int blkdebug_truncate(BlockDriverState *bs, int64_t offset)
40
{
41
- return bdrv_truncate(bs->file->bs, offset);
42
+ return bdrv_truncate(bs->file, offset);
43
}
44
45
static void blkdebug_refresh_filename(BlockDriverState *bs, QDict *options)
46
diff --git a/block/block-backend.c b/block/block-backend.c
44
diff --git a/block/block-backend.c b/block/block-backend.c
47
index XXXXXXX..XXXXXXX 100644
45
index XXXXXXX..XXXXXXX 100644
48
--- a/block/block-backend.c
46
--- a/block/block-backend.c
49
+++ b/block/block-backend.c
47
+++ b/block/block-backend.c
50
@@ -XXX,XX +XXX,XX @@ int blk_truncate(BlockBackend *blk, int64_t offset)
48
@@ -XXX,XX +XXX,XX @@ int blk_truncate(BlockBackend *blk, int64_t offset, bool exact,
51
return -ENOMEDIUM;
49
return -ENOMEDIUM;
52
}
50
}
53
51
54
- return bdrv_truncate(blk_bs(blk), offset);
52
- return bdrv_truncate(blk->root, offset, exact, prealloc, errp);
55
+ return bdrv_truncate(blk->root, offset);
53
+ return bdrv_truncate(blk->root, offset, exact, prealloc, 0, errp);
56
}
54
}
57
55
58
static void blk_pdiscard_entry(void *opaque)
56
int blk_save_vmstate(BlockBackend *blk, const uint8_t *buf,
59
diff --git a/block/crypto.c b/block/crypto.c
57
diff --git a/block/crypto.c b/block/crypto.c
60
index XXXXXXX..XXXXXXX 100644
58
index XXXXXXX..XXXXXXX 100644
61
--- a/block/crypto.c
59
--- a/block/crypto.c
62
+++ b/block/crypto.c
60
+++ b/block/crypto.c
63
@@ -XXX,XX +XXX,XX @@ static int block_crypto_truncate(BlockDriverState *bs, int64_t offset)
61
@@ -XXX,XX +XXX,XX @@ block_crypto_co_truncate(BlockDriverState *bs, int64_t offset, bool exact,
64
62
65
offset += payload_offset;
63
offset += payload_offset;
66
64
67
- return bdrv_truncate(bs->file->bs, offset);
65
- return bdrv_co_truncate(bs->file, offset, exact, prealloc, errp);
68
+ return bdrv_truncate(bs->file, offset);
66
+ return bdrv_co_truncate(bs->file, offset, exact, prealloc, 0, errp);
69
}
67
}
70
68
71
static void block_crypto_close(BlockDriverState *bs)
69
static void block_crypto_close(BlockDriverState *bs)
70
diff --git a/block/io.c b/block/io.c
71
index XXXXXXX..XXXXXXX 100644
72
--- a/block/io.c
73
+++ b/block/io.c
74
@@ -XXX,XX +XXX,XX @@ static void bdrv_parent_cb_resize(BlockDriverState *bs)
75
* 'offset' bytes in length.
76
*/
77
int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
78
- PreallocMode prealloc, Error **errp)
79
+ PreallocMode prealloc, BdrvRequestFlags flags,
80
+ Error **errp)
81
{
82
BlockDriverState *bs = child->bs;
83
BlockDriver *drv = bs->drv;
84
BdrvTrackedRequest req;
85
- BdrvRequestFlags flags = 0;
86
int64_t old_size, new_bytes;
87
int ret;
88
89
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
90
}
91
ret = drv->bdrv_co_truncate(bs, offset, exact, prealloc, flags, errp);
92
} else if (bs->file && drv->is_filter) {
93
- ret = bdrv_co_truncate(bs->file, offset, exact, prealloc, errp);
94
+ ret = bdrv_co_truncate(bs->file, offset, exact, prealloc, flags, errp);
95
} else {
96
error_setg(errp, "Image format driver does not support resize");
97
ret = -ENOTSUP;
98
@@ -XXX,XX +XXX,XX @@ typedef struct TruncateCo {
99
int64_t offset;
100
bool exact;
101
PreallocMode prealloc;
102
+ BdrvRequestFlags flags;
103
Error **errp;
104
int ret;
105
} TruncateCo;
106
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn bdrv_truncate_co_entry(void *opaque)
107
{
108
TruncateCo *tco = opaque;
109
tco->ret = bdrv_co_truncate(tco->child, tco->offset, tco->exact,
110
- tco->prealloc, tco->errp);
111
+ tco->prealloc, tco->flags, tco->errp);
112
aio_wait_kick();
113
}
114
115
int bdrv_truncate(BdrvChild *child, int64_t offset, bool exact,
116
- PreallocMode prealloc, Error **errp)
117
+ PreallocMode prealloc, BdrvRequestFlags flags, Error **errp)
118
{
119
Coroutine *co;
120
TruncateCo tco = {
121
@@ -XXX,XX +XXX,XX @@ int bdrv_truncate(BdrvChild *child, int64_t offset, bool exact,
122
.offset = offset,
123
.exact = exact,
124
.prealloc = prealloc,
125
+ .flags = flags,
126
.errp = errp,
127
.ret = NOT_DONE,
128
};
72
diff --git a/block/parallels.c b/block/parallels.c
129
diff --git a/block/parallels.c b/block/parallels.c
73
index XXXXXXX..XXXXXXX 100644
130
index XXXXXXX..XXXXXXX 100644
74
--- a/block/parallels.c
131
--- a/block/parallels.c
75
+++ b/block/parallels.c
132
+++ b/block/parallels.c
76
@@ -XXX,XX +XXX,XX @@ static int64_t allocate_clusters(BlockDriverState *bs, int64_t sector_num,
133
@@ -XXX,XX +XXX,XX @@ static int64_t allocate_clusters(BlockDriverState *bs, int64_t sector_num,
77
s->data_end << BDRV_SECTOR_BITS,
78
space << BDRV_SECTOR_BITS, 0);
79
} else {
134
} else {
80
- ret = bdrv_truncate(bs->file->bs,
135
ret = bdrv_truncate(bs->file,
81
+ ret = bdrv_truncate(bs->file,
136
(s->data_end + space) << BDRV_SECTOR_BITS,
82
(s->data_end + space) << BDRV_SECTOR_BITS);
137
- false, PREALLOC_MODE_OFF, NULL);
138
+ false, PREALLOC_MODE_OFF, 0, NULL);
83
}
139
}
84
if (ret < 0) {
140
if (ret < 0) {
85
@@ -XXX,XX +XXX,XX @@ static int parallels_check(BlockDriverState *bs, BdrvCheckResult *res,
141
return ret;
86
size - res->image_end_offset);
142
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn parallels_co_check(BlockDriverState *bs,
87
res->leaks += count;
143
* That means we have to pass exact=true.
88
if (fix & BDRV_FIX_LEAKS) {
144
*/
89
- ret = bdrv_truncate(bs->file->bs, res->image_end_offset);
145
ret = bdrv_truncate(bs->file, res->image_end_offset, true,
90
+ ret = bdrv_truncate(bs->file, res->image_end_offset);
146
- PREALLOC_MODE_OFF, &local_err);
147
+ PREALLOC_MODE_OFF, 0, &local_err);
91
if (ret < 0) {
148
if (ret < 0) {
149
error_report_err(local_err);
92
res->check_errors++;
150
res->check_errors++;
93
return ret;
94
@@ -XXX,XX +XXX,XX @@ static int parallels_open(BlockDriverState *bs, QDict *options, int flags,
95
goto fail_options;
96
}
97
if (!bdrv_has_zero_init(bs->file->bs) ||
98
- bdrv_truncate(bs->file->bs, bdrv_getlength(bs->file->bs)) != 0) {
99
+ bdrv_truncate(bs->file, bdrv_getlength(bs->file->bs)) != 0) {
100
s->prealloc_mode = PRL_PREALLOC_MODE_FALLOCATE;
101
}
102
103
@@ -XXX,XX +XXX,XX @@ static void parallels_close(BlockDriverState *bs)
151
@@ -XXX,XX +XXX,XX @@ static void parallels_close(BlockDriverState *bs)
104
}
152
105
153
/* errors are ignored, so we might as well pass exact=true */
106
if (bs->open_flags & BDRV_O_RDWR) {
154
bdrv_truncate(bs->file, s->data_end << BDRV_SECTOR_BITS, true,
107
- bdrv_truncate(bs->file->bs, s->data_end << BDRV_SECTOR_BITS);
155
- PREALLOC_MODE_OFF, NULL);
108
+ bdrv_truncate(bs->file, s->data_end << BDRV_SECTOR_BITS);
156
+ PREALLOC_MODE_OFF, 0, NULL);
109
}
157
}
110
158
111
g_free(s->bat_dirty_bmap);
159
g_free(s->bat_dirty_bmap);
112
diff --git a/block/qcow.c b/block/qcow.c
160
diff --git a/block/qcow.c b/block/qcow.c
113
index XXXXXXX..XXXXXXX 100644
161
index XXXXXXX..XXXXXXX 100644
114
--- a/block/qcow.c
162
--- a/block/qcow.c
115
+++ b/block/qcow.c
163
+++ b/block/qcow.c
116
@@ -XXX,XX +XXX,XX @@ static uint64_t get_cluster_offset(BlockDriverState *bs,
164
@@ -XXX,XX +XXX,XX @@ static int get_cluster_offset(BlockDriverState *bs,
117
/* round to cluster size */
165
return -E2BIG;
118
cluster_offset = (cluster_offset + s->cluster_size - 1) &
166
}
119
~(s->cluster_size - 1);
167
ret = bdrv_truncate(bs->file, cluster_offset + s->cluster_size,
120
- bdrv_truncate(bs->file->bs, cluster_offset + s->cluster_size);
168
- false, PREALLOC_MODE_OFF, NULL);
121
+ bdrv_truncate(bs->file, cluster_offset + s->cluster_size);
169
+ false, PREALLOC_MODE_OFF, 0, NULL);
122
/* if encrypted, we must initialize the cluster
170
if (ret < 0) {
123
content which won't be written */
171
return ret;
124
if (bs->encrypted &&
172
}
125
@@ -XXX,XX +XXX,XX @@ static int qcow_make_empty(BlockDriverState *bs)
173
@@ -XXX,XX +XXX,XX @@ static int qcow_make_empty(BlockDriverState *bs)
126
if (bdrv_pwrite_sync(bs->file, s->l1_table_offset, s->l1_table,
127
l1_length) < 0)
174
l1_length) < 0)
128
return -1;
175
return -1;
129
- ret = bdrv_truncate(bs->file->bs, s->l1_table_offset + l1_length);
176
ret = bdrv_truncate(bs->file, s->l1_table_offset + l1_length, false,
130
+ ret = bdrv_truncate(bs->file, s->l1_table_offset + l1_length);
177
- PREALLOC_MODE_OFF, NULL);
178
+ PREALLOC_MODE_OFF, 0, NULL);
131
if (ret < 0)
179
if (ret < 0)
132
return ret;
180
return ret;
133
181
134
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
182
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
135
index XXXXXXX..XXXXXXX 100644
183
index XXXXXXX..XXXXXXX 100644
136
--- a/block/qcow2-refcount.c
184
--- a/block/qcow2-refcount.c
137
+++ b/block/qcow2-refcount.c
185
+++ b/block/qcow2-refcount.c
138
@@ -XXX,XX +XXX,XX @@ static int check_refblocks(BlockDriverState *bs, BdrvCheckResult *res,
186
@@ -XXX,XX +XXX,XX @@ static int check_refblocks(BlockDriverState *bs, BdrvCheckResult *res,
187
}
188
189
ret = bdrv_truncate(bs->file, offset + s->cluster_size, false,
190
- PREALLOC_MODE_OFF, &local_err);
191
+ PREALLOC_MODE_OFF, 0, &local_err);
192
if (ret < 0) {
193
error_report_err(local_err);
139
goto resize_fail;
194
goto resize_fail;
140
}
141
142
- ret = bdrv_truncate(bs->file->bs, offset + s->cluster_size);
143
+ ret = bdrv_truncate(bs->file, offset + s->cluster_size);
144
if (ret < 0) {
145
goto resize_fail;
146
}
147
diff --git a/block/qcow2.c b/block/qcow2.c
195
diff --git a/block/qcow2.c b/block/qcow2.c
148
index XXXXXXX..XXXXXXX 100644
196
index XXXXXXX..XXXXXXX 100644
149
--- a/block/qcow2.c
197
--- a/block/qcow2.c
150
+++ b/block/qcow2.c
198
+++ b/block/qcow2.c
151
@@ -XXX,XX +XXX,XX @@ qcow2_co_pwritev_compressed(BlockDriverState *bs, uint64_t offset,
199
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn preallocate_co(BlockDriverState *bs, uint64_t offset,
152
/* align end of file to a sector boundary to ease reading with
200
mode = PREALLOC_MODE_OFF;
153
sector based I/Os */
201
}
154
cluster_offset = bdrv_getlength(bs->file->bs);
202
ret = bdrv_co_truncate(s->data_file, host_offset + cur_bytes, false,
155
- return bdrv_truncate(bs->file->bs, cluster_offset);
203
- mode, errp);
156
+ return bdrv_truncate(bs->file, cluster_offset);
204
+ mode, 0, errp);
157
}
205
if (ret < 0) {
158
206
return ret;
159
buf = qemu_blockalign(bs, s->cluster_size);
207
}
208
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
209
* always fulfilled, so there is no need to pass it on.)
210
*/
211
bdrv_co_truncate(bs->file, (last_cluster + 1) * s->cluster_size,
212
- false, PREALLOC_MODE_OFF, &local_err);
213
+ false, PREALLOC_MODE_OFF, 0, &local_err);
214
if (local_err) {
215
warn_reportf_err(local_err,
216
"Failed to truncate the tail of the image: ");
217
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
218
* file should be resized to the exact target size, too,
219
* so we pass @exact here.
220
*/
221
- ret = bdrv_co_truncate(s->data_file, offset, exact, prealloc, errp);
222
+ ret = bdrv_co_truncate(s->data_file, offset, exact, prealloc, 0,
223
+ errp);
224
if (ret < 0) {
225
goto fail;
226
}
227
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
228
new_file_size = allocation_start +
229
nb_new_data_clusters * s->cluster_size;
230
/* Image file grows, so @exact does not matter */
231
- ret = bdrv_co_truncate(bs->file, new_file_size, false, prealloc, errp);
232
+ ret = bdrv_co_truncate(bs->file, new_file_size, false, prealloc, 0,
233
+ errp);
234
if (ret < 0) {
235
error_prepend(errp, "Failed to resize underlying file: ");
236
qcow2_free_clusters(bs, allocation_start,
237
@@ -XXX,XX +XXX,XX @@ qcow2_co_pwritev_compressed_part(BlockDriverState *bs,
238
if (len < 0) {
239
return len;
240
}
241
- return bdrv_co_truncate(bs->file, len, false, PREALLOC_MODE_OFF, NULL);
242
+ return bdrv_co_truncate(bs->file, len, false, PREALLOC_MODE_OFF, 0,
243
+ NULL);
244
}
245
246
if (offset_into_cluster(s, offset)) {
160
@@ -XXX,XX +XXX,XX @@ static int make_completely_empty(BlockDriverState *bs)
247
@@ -XXX,XX +XXX,XX @@ static int make_completely_empty(BlockDriverState *bs)
248
}
249
250
ret = bdrv_truncate(bs->file, (3 + l1_clusters) * s->cluster_size, false,
251
- PREALLOC_MODE_OFF, &local_err);
252
+ PREALLOC_MODE_OFF, 0, &local_err);
253
if (ret < 0) {
254
error_report_err(local_err);
161
goto fail;
255
goto fail;
162
}
163
164
- ret = bdrv_truncate(bs->file->bs, (3 + l1_clusters) * s->cluster_size);
165
+ ret = bdrv_truncate(bs->file, (3 + l1_clusters) * s->cluster_size);
166
if (ret < 0) {
167
goto fail;
168
}
169
diff --git a/block/raw-format.c b/block/raw-format.c
256
diff --git a/block/raw-format.c b/block/raw-format.c
170
index XXXXXXX..XXXXXXX 100644
257
index XXXXXXX..XXXXXXX 100644
171
--- a/block/raw-format.c
258
--- a/block/raw-format.c
172
+++ b/block/raw-format.c
259
+++ b/block/raw-format.c
173
@@ -XXX,XX +XXX,XX @@ static int raw_truncate(BlockDriverState *bs, int64_t offset)
260
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset,
174
261
175
s->size = offset;
262
s->size = offset;
176
offset += s->offset;
263
offset += s->offset;
177
- return bdrv_truncate(bs->file->bs, offset);
264
- return bdrv_co_truncate(bs->file, offset, exact, prealloc, errp);
178
+ return bdrv_truncate(bs->file, offset);
265
+ return bdrv_co_truncate(bs->file, offset, exact, prealloc, 0, errp);
179
}
266
}
180
267
181
static int raw_media_changed(BlockDriverState *bs)
268
static void raw_eject(BlockDriverState *bs, bool eject_flag)
182
diff --git a/block/vhdx-log.c b/block/vhdx-log.c
269
diff --git a/block/vhdx-log.c b/block/vhdx-log.c
183
index XXXXXXX..XXXXXXX 100644
270
index XXXXXXX..XXXXXXX 100644
184
--- a/block/vhdx-log.c
271
--- a/block/vhdx-log.c
185
+++ b/block/vhdx-log.c
272
+++ b/block/vhdx-log.c
186
@@ -XXX,XX +XXX,XX @@ static int vhdx_log_flush(BlockDriverState *bs, BDRVVHDXState *s,
273
@@ -XXX,XX +XXX,XX @@ static int vhdx_log_flush(BlockDriverState *bs, BDRVVHDXState *s,
187
if (new_file_size % (1024*1024)) {
274
goto exit;
188
/* round up to nearest 1MB boundary */
275
}
189
new_file_size = ((new_file_size >> 20) + 1) << 20;
276
ret = bdrv_truncate(bs->file, new_file_size, false,
190
- bdrv_truncate(bs->file->bs, new_file_size);
277
- PREALLOC_MODE_OFF, NULL);
191
+ bdrv_truncate(bs->file, new_file_size);
278
+ PREALLOC_MODE_OFF, 0, NULL);
192
}
279
if (ret < 0) {
193
}
280
goto exit;
194
qemu_vfree(desc_entries);
281
}
195
diff --git a/block/vhdx.c b/block/vhdx.c
282
diff --git a/block/vhdx.c b/block/vhdx.c
196
index XXXXXXX..XXXXXXX 100644
283
index XXXXXXX..XXXXXXX 100644
197
--- a/block/vhdx.c
284
--- a/block/vhdx.c
198
+++ b/block/vhdx.c
285
+++ b/block/vhdx.c
199
@@ -XXX,XX +XXX,XX @@ static int vhdx_allocate_block(BlockDriverState *bs, BDRVVHDXState *s,
286
@@ -XXX,XX +XXX,XX @@ static int vhdx_allocate_block(BlockDriverState *bs, BDRVVHDXState *s,
200
/* per the spec, the address for a block is in units of 1MB */
287
}
201
*new_offset = ROUND_UP(*new_offset, 1024 * 1024);
288
202
289
return bdrv_truncate(bs->file, *new_offset + s->block_size, false,
203
- return bdrv_truncate(bs->file->bs, *new_offset + s->block_size);
290
- PREALLOC_MODE_OFF, NULL);
204
+ return bdrv_truncate(bs->file, *new_offset + s->block_size);
291
+ PREALLOC_MODE_OFF, 0, NULL);
205
}
292
}
206
293
207
/*
294
/*
208
diff --git a/include/block/block.h b/include/block/block.h
295
diff --git a/block/vmdk.c b/block/vmdk.c
209
index XXXXXXX..XXXXXXX 100644
296
index XXXXXXX..XXXXXXX 100644
210
--- a/include/block/block.h
297
--- a/block/vmdk.c
211
+++ b/include/block/block.h
298
+++ b/block/vmdk.c
212
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs,
299
@@ -XXX,XX +XXX,XX @@ vmdk_co_pwritev_compressed(BlockDriverState *bs, uint64_t offset,
213
const char *backing_file);
300
}
214
int bdrv_get_backing_file_depth(BlockDriverState *bs);
301
length = QEMU_ALIGN_UP(length, BDRV_SECTOR_SIZE);
215
void bdrv_refresh_filename(BlockDriverState *bs);
302
ret = bdrv_truncate(s->extents[i].file, length, false,
216
-int bdrv_truncate(BlockDriverState *bs, int64_t offset);
303
- PREALLOC_MODE_OFF, NULL);
217
+int bdrv_truncate(BdrvChild *child, int64_t offset);
304
+ PREALLOC_MODE_OFF, 0, NULL);
218
int64_t bdrv_nb_sectors(BlockDriverState *bs);
305
if (ret < 0) {
219
int64_t bdrv_getlength(BlockDriverState *bs);
306
return ret;
220
int64_t bdrv_get_allocated_file_size(BlockDriverState *bs);
307
}
308
diff --git a/tests/test-block-iothread.c b/tests/test-block-iothread.c
309
index XXXXXXX..XXXXXXX 100644
310
--- a/tests/test-block-iothread.c
311
+++ b/tests/test-block-iothread.c
312
@@ -XXX,XX +XXX,XX @@ static void test_sync_op_truncate(BdrvChild *c)
313
int ret;
314
315
/* Normal success path */
316
- ret = bdrv_truncate(c, 65536, false, PREALLOC_MODE_OFF, NULL);
317
+ ret = bdrv_truncate(c, 65536, false, PREALLOC_MODE_OFF, 0, NULL);
318
g_assert_cmpint(ret, ==, 0);
319
320
/* Early error: Negative offset */
321
- ret = bdrv_truncate(c, -2, false, PREALLOC_MODE_OFF, NULL);
322
+ ret = bdrv_truncate(c, -2, false, PREALLOC_MODE_OFF, 0, NULL);
323
g_assert_cmpint(ret, ==, -EINVAL);
324
325
/* Error: Read-only image */
326
c->bs->read_only = true;
327
c->bs->open_flags &= ~BDRV_O_RDWR;
328
329
- ret = bdrv_truncate(c, 65536, false, PREALLOC_MODE_OFF, NULL);
330
+ ret = bdrv_truncate(c, 65536, false, PREALLOC_MODE_OFF, 0, NULL);
331
g_assert_cmpint(ret, ==, -EACCES);
332
333
c->bs->read_only = false;
221
--
334
--
222
1.8.3.1
335
2.25.3
223
336
224
337
diff view generated by jsdifflib
1
The way that attaching bs->file worked was a bit unusual in that it was
1
Now that node level interface bdrv_truncate() supports passing request
2
the only child that would be attached to a node which is not opened yet.
2
flags to the block driver, expose this on the BlockBackend level, too.
3
Because of this, the block layer couldn't know yet which permissions the
4
driver would eventually need.
5
6
This patch moves the point where bs->file is attached to the beginning
7
of the individual .bdrv_open() implementations, so drivers already know
8
what they are going to do with the child. This is also more consistent
9
with how driver-specific children work.
10
11
For a moment, bdrv_open() gets its own BdrvChild to perform image
12
probing, but instead of directly assigning this BdrvChild to the BDS, it
13
becomes a temporary one and the node name is passed as an option to the
14
drivers, so that they can simply use bdrv_open_child() to create another
15
reference for their own use.
16
17
This duplicated child for (the not opened yet) bs is not the final
18
state, a follow-up patch will change the image probing code to use a
19
BlockBackend, which is completely independent of bs.
20
3
21
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
6
Reviewed-by: Alberto Garcia <berto@igalia.com>
22
Reviewed-by: Max Reitz <mreitz@redhat.com>
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
8
Message-Id: <20200424125448.63318-4-kwolf@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
23
---
10
---
24
block.c | 35 ++++++++++++++++++++++++-----------
11
include/sysemu/block-backend.h | 2 +-
25
block/bochs.c | 6 ++++++
12
block.c | 3 ++-
26
block/cloop.c | 6 ++++++
13
block/block-backend.c | 4 ++--
27
block/crypto.c | 6 ++++++
14
block/commit.c | 4 ++--
28
block/dmg.c | 6 ++++++
15
block/crypto.c | 2 +-
29
block/parallels.c | 6 ++++++
16
block/mirror.c | 2 +-
30
block/qcow.c | 6 ++++++
17
block/qcow2.c | 4 ++--
31
block/qcow2.c | 18 +++++++++++++++---
18
block/qed.c | 2 +-
32
block/qed.c | 18 +++++++++++++++---
19
block/vdi.c | 2 +-
33
block/raw-format.c | 6 ++++++
20
block/vhdx.c | 4 ++--
34
block/replication.c | 6 ++++++
21
block/vmdk.c | 6 +++---
35
block/vdi.c | 6 ++++++
22
block/vpc.c | 2 +-
36
block/vhdx.c | 6 ++++++
23
blockdev.c | 2 +-
37
block/vmdk.c | 6 ++++++
24
qemu-img.c | 2 +-
38
block/vpc.c | 6 ++++++
25
qemu-io-cmds.c | 2 +-
39
tests/qemu-iotests/051.out | 4 ++--
26
15 files changed, 22 insertions(+), 21 deletions(-)
40
tests/qemu-iotests/051.pc.out | 4 ++--
27
41
17 files changed, 130 insertions(+), 21 deletions(-)
28
diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h
42
29
index XXXXXXX..XXXXXXX 100644
30
--- a/include/sysemu/block-backend.h
31
+++ b/include/sysemu/block-backend.h
32
@@ -XXX,XX +XXX,XX @@ int coroutine_fn blk_co_pwrite_zeroes(BlockBackend *blk, int64_t offset,
33
int blk_pwrite_compressed(BlockBackend *blk, int64_t offset, const void *buf,
34
int bytes);
35
int blk_truncate(BlockBackend *blk, int64_t offset, bool exact,
36
- PreallocMode prealloc, Error **errp);
37
+ PreallocMode prealloc, BdrvRequestFlags flags, Error **errp);
38
int blk_pdiscard(BlockBackend *blk, int64_t offset, int bytes);
39
int blk_save_vmstate(BlockBackend *blk, const uint8_t *buf,
40
int64_t pos, int size);
43
diff --git a/block.c b/block.c
41
diff --git a/block.c b/block.c
44
index XXXXXXX..XXXXXXX 100644
42
index XXXXXXX..XXXXXXX 100644
45
--- a/block.c
43
--- a/block.c
46
+++ b/block.c
44
+++ b/block.c
47
@@ -XXX,XX +XXX,XX @@ static int bdrv_open_common(BlockDriverState *bs, BdrvChild *file,
45
@@ -XXX,XX +XXX,XX @@ static int64_t create_file_fallback_truncate(BlockBackend *blk,
48
assert(!drv->bdrv_needs_filename || filename != NULL);
46
int64_t size;
49
ret = drv->bdrv_file_open(bs, options, open_flags, &local_err);
50
} else {
51
- if (file == NULL) {
52
- error_setg(errp, "Can't use '%s' as a block driver for the "
53
- "protocol level", drv->format_name);
54
- ret = -EINVAL;
55
- goto free_and_fail;
56
- }
57
- bs->file = file;
58
ret = drv->bdrv_open(bs, options, open_flags, &local_err);
59
}
60
61
@@ -XXX,XX +XXX,XX @@ static int bdrv_open_common(BlockDriverState *bs, BdrvChild *file,
62
return 0;
63
64
free_and_fail:
65
- bs->file = NULL;
66
g_free(bs->opaque);
67
bs->opaque = NULL;
68
bs->drv = NULL;
69
@@ -XXX,XX +XXX,XX @@ void bdrv_unref_child(BlockDriverState *parent, BdrvChild *child)
70
}
71
72
if (child->bs->inherits_from == parent) {
73
- child->bs->inherits_from = NULL;
74
+ BdrvChild *c;
75
+
76
+ /* Remove inherits_from only when the last reference between parent and
77
+ * child->bs goes away. */
78
+ QLIST_FOREACH(c, &parent->children, next) {
79
+ if (c != child && c->bs == child->bs) {
80
+ break;
81
+ }
82
+ }
83
+ if (c == NULL) {
84
+ child->bs->inherits_from = NULL;
85
+ }
86
}
87
88
bdrv_root_unref_child(child);
89
@@ -XXX,XX +XXX,XX @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
90
qdict_del(options, "backing");
91
}
92
93
- /* Open image file without format layer */
94
+ /* Open image file without format layer. This BdrvChild is only used for
95
+ * probing, the block drivers will do their own bdrv_open_child() for the
96
+ * same BDS, which is why we put the node name back into options. */
97
if ((flags & BDRV_O_PROTOCOL) == 0) {
98
+ /* FIXME Shouldn't attach a child to a node that isn't opened yet. */
99
file = bdrv_open_child(filename, options, "file", bs,
100
&child_file, true, &local_err);
101
if (local_err) {
102
goto fail;
103
}
104
+ if (file != NULL) {
105
+ qdict_put(options, "file",
106
+ qstring_from_str(bdrv_get_node_name(file->bs)));
107
+ }
108
}
109
110
/* Image format probing */
111
@@ -XXX,XX +XXX,XX @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
112
goto fail;
113
}
114
115
- if (file && (bs->file != file)) {
116
+ if (file) {
117
bdrv_unref_child(bs, file);
118
file = NULL;
119
}
120
@@ -XXX,XX +XXX,XX @@ fail:
121
if (file != NULL) {
122
bdrv_unref_child(bs, file);
123
}
124
+ if (bs->file != NULL) {
125
+ bdrv_unref_child(bs, bs->file);
126
+ }
127
QDECREF(snapshot_options);
128
QDECREF(bs->explicit_options);
129
QDECREF(bs->options);
130
diff --git a/block/bochs.c b/block/bochs.c
131
index XXXXXXX..XXXXXXX 100644
132
--- a/block/bochs.c
133
+++ b/block/bochs.c
134
@@ -XXX,XX +XXX,XX @@ static int bochs_open(BlockDriverState *bs, QDict *options, int flags,
135
struct bochs_header bochs;
136
int ret;
47
int ret;
137
48
138
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file,
49
- ret = blk_truncate(blk, minimum_size, false, PREALLOC_MODE_OFF, &local_err);
139
+ false, errp);
50
+ ret = blk_truncate(blk, minimum_size, false, PREALLOC_MODE_OFF, 0,
140
+ if (!bs->file) {
51
+ &local_err);
141
+ return -EINVAL;
52
if (ret < 0 && ret != -ENOTSUP) {
142
+ }
53
error_propagate(errp, local_err);
143
+
54
return ret;
144
bs->read_only = true; /* no write support yet */
55
diff --git a/block/block-backend.c b/block/block-backend.c
145
56
index XXXXXXX..XXXXXXX 100644
146
ret = bdrv_pread(bs->file, 0, &bochs, sizeof(bochs));
57
--- a/block/block-backend.c
147
diff --git a/block/cloop.c b/block/cloop.c
58
+++ b/block/block-backend.c
148
index XXXXXXX..XXXXXXX 100644
59
@@ -XXX,XX +XXX,XX @@ int blk_pwrite_compressed(BlockBackend *blk, int64_t offset, const void *buf,
149
--- a/block/cloop.c
60
}
150
+++ b/block/cloop.c
61
151
@@ -XXX,XX +XXX,XX @@ static int cloop_open(BlockDriverState *bs, QDict *options, int flags,
62
int blk_truncate(BlockBackend *blk, int64_t offset, bool exact,
152
uint32_t offsets_size, max_compressed_block_size = 1, i;
63
- PreallocMode prealloc, Error **errp)
153
int ret;
64
+ PreallocMode prealloc, BdrvRequestFlags flags, Error **errp)
154
65
{
155
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file,
66
if (!blk_is_available(blk)) {
156
+ false, errp);
67
error_setg(errp, "No medium inserted");
157
+ if (!bs->file) {
68
return -ENOMEDIUM;
158
+ return -EINVAL;
69
}
159
+ }
70
160
+
71
- return bdrv_truncate(blk->root, offset, exact, prealloc, 0, errp);
161
bs->read_only = true;
72
+ return bdrv_truncate(blk->root, offset, exact, prealloc, flags, errp);
162
73
}
163
/* read header */
74
75
int blk_save_vmstate(BlockBackend *blk, const uint8_t *buf,
76
diff --git a/block/commit.c b/block/commit.c
77
index XXXXXXX..XXXXXXX 100644
78
--- a/block/commit.c
79
+++ b/block/commit.c
80
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn commit_run(Job *job, Error **errp)
81
}
82
83
if (base_len < len) {
84
- ret = blk_truncate(s->base, len, false, PREALLOC_MODE_OFF, NULL);
85
+ ret = blk_truncate(s->base, len, false, PREALLOC_MODE_OFF, 0, NULL);
86
if (ret) {
87
goto out;
88
}
89
@@ -XXX,XX +XXX,XX @@ int bdrv_commit(BlockDriverState *bs)
90
* grow the backing file image if possible. If not possible,
91
* we must return an error */
92
if (length > backing_length) {
93
- ret = blk_truncate(backing, length, false, PREALLOC_MODE_OFF,
94
+ ret = blk_truncate(backing, length, false, PREALLOC_MODE_OFF, 0,
95
&local_err);
96
if (ret < 0) {
97
error_report_err(local_err);
164
diff --git a/block/crypto.c b/block/crypto.c
98
diff --git a/block/crypto.c b/block/crypto.c
165
index XXXXXXX..XXXXXXX 100644
99
index XXXXXXX..XXXXXXX 100644
166
--- a/block/crypto.c
100
--- a/block/crypto.c
167
+++ b/block/crypto.c
101
+++ b/block/crypto.c
168
@@ -XXX,XX +XXX,XX @@ static int block_crypto_open_generic(QCryptoBlockFormat format,
102
@@ -XXX,XX +XXX,XX @@ static ssize_t block_crypto_init_func(QCryptoBlock *block,
169
QCryptoBlockOpenOptions *open_opts = NULL;
103
* which will be used by the crypto header
170
unsigned int cflags = 0;
104
*/
171
105
return blk_truncate(data->blk, data->size + headerlen, false,
172
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file,
106
- data->prealloc, errp);
173
+ false, errp);
107
+ data->prealloc, 0, errp);
174
+ if (!bs->file) {
108
}
175
+ return -EINVAL;
109
176
+ }
110
177
+
111
diff --git a/block/mirror.c b/block/mirror.c
178
opts = qemu_opts_create(opts_spec, NULL, 0, &error_abort);
112
index XXXXXXX..XXXXXXX 100644
179
qemu_opts_absorb_qdict(opts, options, &local_err);
113
--- a/block/mirror.c
180
if (local_err) {
114
+++ b/block/mirror.c
181
diff --git a/block/dmg.c b/block/dmg.c
115
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn mirror_run(Job *job, Error **errp)
182
index XXXXXXX..XXXXXXX 100644
116
183
--- a/block/dmg.c
117
if (s->bdev_length > base_length) {
184
+++ b/block/dmg.c
118
ret = blk_truncate(s->target, s->bdev_length, false,
185
@@ -XXX,XX +XXX,XX @@ static int dmg_open(BlockDriverState *bs, QDict *options, int flags,
119
- PREALLOC_MODE_OFF, NULL);
186
int64_t offset;
120
+ PREALLOC_MODE_OFF, 0, NULL);
187
int ret;
121
if (ret < 0) {
188
122
goto immediate_exit;
189
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file,
123
}
190
+ false, errp);
191
+ if (!bs->file) {
192
+ return -EINVAL;
193
+ }
194
+
195
block_module_load_one("dmg-bz2");
196
bs->read_only = true;
197
198
diff --git a/block/parallels.c b/block/parallels.c
199
index XXXXXXX..XXXXXXX 100644
200
--- a/block/parallels.c
201
+++ b/block/parallels.c
202
@@ -XXX,XX +XXX,XX @@ static int parallels_open(BlockDriverState *bs, QDict *options, int flags,
203
Error *local_err = NULL;
204
char *buf;
205
206
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file,
207
+ false, errp);
208
+ if (!bs->file) {
209
+ return -EINVAL;
210
+ }
211
+
212
ret = bdrv_pread(bs->file, 0, &ph, sizeof(ph));
213
if (ret < 0) {
214
goto fail;
215
diff --git a/block/qcow.c b/block/qcow.c
216
index XXXXXXX..XXXXXXX 100644
217
--- a/block/qcow.c
218
+++ b/block/qcow.c
219
@@ -XXX,XX +XXX,XX @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags,
220
QCowHeader header;
221
Error *local_err = NULL;
222
223
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file,
224
+ false, errp);
225
+ if (!bs->file) {
226
+ return -EINVAL;
227
+ }
228
+
229
ret = bdrv_pread(bs->file, 0, &header, sizeof(header));
230
if (ret < 0) {
231
goto fail;
232
diff --git a/block/qcow2.c b/block/qcow2.c
124
diff --git a/block/qcow2.c b/block/qcow2.c
233
index XXXXXXX..XXXXXXX 100644
125
index XXXXXXX..XXXXXXX 100644
234
--- a/block/qcow2.c
126
--- a/block/qcow2.c
235
+++ b/block/qcow2.c
127
+++ b/block/qcow2.c
236
@@ -XXX,XX +XXX,XX @@ static int qcow2_update_options(BlockDriverState *bs, QDict *options,
128
@@ -XXX,XX +XXX,XX @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp)
237
return ret;
129
238
}
130
/* Okay, now that we have a valid image, let's give it the right size */
239
131
ret = blk_truncate(blk, qcow2_opts->size, false, qcow2_opts->preallocation,
240
-static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
132
- errp);
241
- Error **errp)
133
+ 0, errp);
242
+static int qcow2_do_open(BlockDriverState *bs, QDict *options, int flags,
134
if (ret < 0) {
243
+ Error **errp)
135
error_prepend(errp, "Could not resize image: ");
244
{
136
goto out;
245
BDRVQcow2State *s = bs->opaque;
137
@@ -XXX,XX +XXX,XX @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts,
246
unsigned int len, i;
138
* Amending image options should ensure that the image has
247
@@ -XXX,XX +XXX,XX @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
139
* exactly the given new values, so pass exact=true here.
248
return ret;
140
*/
249
}
141
- ret = blk_truncate(blk, new_size, true, PREALLOC_MODE_OFF, errp);
250
142
+ ret = blk_truncate(blk, new_size, true, PREALLOC_MODE_OFF, 0, errp);
251
+static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
143
blk_unref(blk);
252
+ Error **errp)
144
if (ret < 0) {
253
+{
145
return ret;
254
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file,
255
+ false, errp);
256
+ if (!bs->file) {
257
+ return -EINVAL;
258
+ }
259
+
260
+ return qcow2_do_open(bs, options, flags, errp);
261
+}
262
+
263
static void qcow2_refresh_limits(BlockDriverState *bs, Error **errp)
264
{
265
BDRVQcow2State *s = bs->opaque;
266
@@ -XXX,XX +XXX,XX @@ static void qcow2_invalidate_cache(BlockDriverState *bs, Error **errp)
267
options = qdict_clone_shallow(bs->options);
268
269
flags &= ~BDRV_O_INACTIVE;
270
- ret = qcow2_open(bs, options, flags, &local_err);
271
+ ret = qcow2_do_open(bs, options, flags, &local_err);
272
QDECREF(options);
273
if (local_err) {
274
error_propagate(errp, local_err);
275
diff --git a/block/qed.c b/block/qed.c
146
diff --git a/block/qed.c b/block/qed.c
276
index XXXXXXX..XXXXXXX 100644
147
index XXXXXXX..XXXXXXX 100644
277
--- a/block/qed.c
148
--- a/block/qed.c
278
+++ b/block/qed.c
149
+++ b/block/qed.c
279
@@ -XXX,XX +XXX,XX @@ static void bdrv_qed_drain(BlockDriverState *bs)
150
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_qed_co_create(BlockdevCreateOptions *opts,
280
}
151
* The QED format associates file length with allocation status,
281
}
152
* so a new file (which is empty) must have a length of 0.
282
153
*/
283
-static int bdrv_qed_open(BlockDriverState *bs, QDict *options, int flags,
154
- ret = blk_truncate(blk, 0, true, PREALLOC_MODE_OFF, errp);
284
- Error **errp)
155
+ ret = blk_truncate(blk, 0, true, PREALLOC_MODE_OFF, 0, errp);
285
+static int bdrv_qed_do_open(BlockDriverState *bs, QDict *options, int flags,
156
if (ret < 0) {
286
+ Error **errp)
157
goto out;
287
{
158
}
288
BDRVQEDState *s = bs->opaque;
289
QEDHeader le_header;
290
@@ -XXX,XX +XXX,XX @@ out:
291
return ret;
292
}
293
294
+static int bdrv_qed_open(BlockDriverState *bs, QDict *options, int flags,
295
+ Error **errp)
296
+{
297
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file,
298
+ false, errp);
299
+ if (!bs->file) {
300
+ return -EINVAL;
301
+ }
302
+
303
+ return bdrv_qed_do_open(bs, options, flags, errp);
304
+}
305
+
306
static void bdrv_qed_refresh_limits(BlockDriverState *bs, Error **errp)
307
{
308
BDRVQEDState *s = bs->opaque;
309
@@ -XXX,XX +XXX,XX @@ static void bdrv_qed_invalidate_cache(BlockDriverState *bs, Error **errp)
310
bdrv_qed_close(bs);
311
312
memset(s, 0, sizeof(BDRVQEDState));
313
- ret = bdrv_qed_open(bs, NULL, bs->open_flags, &local_err);
314
+ ret = bdrv_qed_do_open(bs, NULL, bs->open_flags, &local_err);
315
if (local_err) {
316
error_propagate(errp, local_err);
317
error_prepend(errp, "Could not reopen qed layer: ");
318
diff --git a/block/raw-format.c b/block/raw-format.c
319
index XXXXXXX..XXXXXXX 100644
320
--- a/block/raw-format.c
321
+++ b/block/raw-format.c
322
@@ -XXX,XX +XXX,XX @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags,
323
BDRVRawState *s = bs->opaque;
324
int ret;
325
326
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file,
327
+ false, errp);
328
+ if (!bs->file) {
329
+ return -EINVAL;
330
+ }
331
+
332
bs->sg = bs->file->bs->sg;
333
bs->supported_write_flags = BDRV_REQ_FUA &
334
bs->file->bs->supported_write_flags;
335
diff --git a/block/replication.c b/block/replication.c
336
index XXXXXXX..XXXXXXX 100644
337
--- a/block/replication.c
338
+++ b/block/replication.c
339
@@ -XXX,XX +XXX,XX @@ static int replication_open(BlockDriverState *bs, QDict *options,
340
const char *mode;
341
const char *top_id;
342
343
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file,
344
+ false, errp);
345
+ if (!bs->file) {
346
+ return -EINVAL;
347
+ }
348
+
349
ret = -EINVAL;
350
opts = qemu_opts_create(&replication_runtime_opts, NULL, 0, &error_abort);
351
qemu_opts_absorb_qdict(opts, options, &local_err);
352
diff --git a/block/vdi.c b/block/vdi.c
159
diff --git a/block/vdi.c b/block/vdi.c
353
index XXXXXXX..XXXXXXX 100644
160
index XXXXXXX..XXXXXXX 100644
354
--- a/block/vdi.c
161
--- a/block/vdi.c
355
+++ b/block/vdi.c
162
+++ b/block/vdi.c
356
@@ -XXX,XX +XXX,XX @@ static int vdi_open(BlockDriverState *bs, QDict *options, int flags,
163
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vdi_co_do_create(BlockdevCreateOptions *create_options,
357
int ret;
164
358
Error *local_err = NULL;
165
if (image_type == VDI_TYPE_STATIC) {
359
166
ret = blk_truncate(blk, offset + blocks * block_size, false,
360
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file,
167
- PREALLOC_MODE_OFF, errp);
361
+ false, errp);
168
+ PREALLOC_MODE_OFF, 0, errp);
362
+ if (!bs->file) {
169
if (ret < 0) {
363
+ return -EINVAL;
170
error_prepend(errp, "Failed to statically allocate file");
364
+ }
171
goto exit;
365
+
366
logout("\n");
367
368
ret = bdrv_read(bs->file, 0, (uint8_t *)&header, 1);
369
diff --git a/block/vhdx.c b/block/vhdx.c
172
diff --git a/block/vhdx.c b/block/vhdx.c
370
index XXXXXXX..XXXXXXX 100644
173
index XXXXXXX..XXXXXXX 100644
371
--- a/block/vhdx.c
174
--- a/block/vhdx.c
372
+++ b/block/vhdx.c
175
+++ b/block/vhdx.c
373
@@ -XXX,XX +XXX,XX @@ static int vhdx_open(BlockDriverState *bs, QDict *options, int flags,
176
@@ -XXX,XX +XXX,XX @@ static int vhdx_create_bat(BlockBackend *blk, BDRVVHDXState *s,
374
uint64_t signature;
177
/* All zeroes, so we can just extend the file - the end of the BAT
375
Error *local_err = NULL;
178
* is the furthest thing we have written yet */
376
179
ret = blk_truncate(blk, data_file_offset, false, PREALLOC_MODE_OFF,
377
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file,
180
- errp);
378
+ false, errp);
181
+ 0, errp);
379
+ if (!bs->file) {
182
if (ret < 0) {
380
+ return -EINVAL;
183
goto exit;
381
+ }
184
}
382
+
185
} else if (type == VHDX_TYPE_FIXED) {
383
s->bat = NULL;
186
ret = blk_truncate(blk, data_file_offset + image_size, false,
384
s->first_visible_write = true;
187
- PREALLOC_MODE_OFF, errp);
385
188
+ PREALLOC_MODE_OFF, 0, errp);
189
if (ret < 0) {
190
goto exit;
191
}
386
diff --git a/block/vmdk.c b/block/vmdk.c
192
diff --git a/block/vmdk.c b/block/vmdk.c
387
index XXXXXXX..XXXXXXX 100644
193
index XXXXXXX..XXXXXXX 100644
388
--- a/block/vmdk.c
194
--- a/block/vmdk.c
389
+++ b/block/vmdk.c
195
+++ b/block/vmdk.c
390
@@ -XXX,XX +XXX,XX @@ static int vmdk_open(BlockDriverState *bs, QDict *options, int flags,
196
@@ -XXX,XX +XXX,XX @@ static int vmdk_init_extent(BlockBackend *blk,
391
uint32_t magic;
197
int gd_buf_size;
392
Error *local_err = NULL;
198
393
199
if (flat) {
394
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file,
200
- ret = blk_truncate(blk, filesize, false, PREALLOC_MODE_OFF, errp);
395
+ false, errp);
201
+ ret = blk_truncate(blk, filesize, false, PREALLOC_MODE_OFF, 0, errp);
396
+ if (!bs->file) {
202
goto exit;
397
+ return -EINVAL;
203
}
398
+ }
204
magic = cpu_to_be32(VMDK4_MAGIC);
399
+
205
@@ -XXX,XX +XXX,XX @@ static int vmdk_init_extent(BlockBackend *blk,
400
buf = vmdk_read_desc(bs->file, 0, errp);
206
}
401
if (!buf) {
207
402
return -EINVAL;
208
ret = blk_truncate(blk, le64_to_cpu(header.grain_offset) << 9, false,
209
- PREALLOC_MODE_OFF, errp);
210
+ PREALLOC_MODE_OFF, 0, errp);
211
if (ret < 0) {
212
goto exit;
213
}
214
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vmdk_co_do_create(int64_t size,
215
/* bdrv_pwrite write padding zeros to align to sector, we don't need that
216
* for description file */
217
if (desc_offset == 0) {
218
- ret = blk_truncate(blk, desc_len, false, PREALLOC_MODE_OFF, errp);
219
+ ret = blk_truncate(blk, desc_len, false, PREALLOC_MODE_OFF, 0, errp);
220
if (ret < 0) {
221
goto exit;
222
}
403
diff --git a/block/vpc.c b/block/vpc.c
223
diff --git a/block/vpc.c b/block/vpc.c
404
index XXXXXXX..XXXXXXX 100644
224
index XXXXXXX..XXXXXXX 100644
405
--- a/block/vpc.c
225
--- a/block/vpc.c
406
+++ b/block/vpc.c
226
+++ b/block/vpc.c
407
@@ -XXX,XX +XXX,XX @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags,
227
@@ -XXX,XX +XXX,XX @@ static int create_fixed_disk(BlockBackend *blk, uint8_t *buf,
408
int disk_type = VHD_DYNAMIC;
228
/* Add footer to total size */
409
int ret;
229
total_size += HEADER_SIZE;
410
230
411
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file,
231
- ret = blk_truncate(blk, total_size, false, PREALLOC_MODE_OFF, errp);
412
+ false, errp);
232
+ ret = blk_truncate(blk, total_size, false, PREALLOC_MODE_OFF, 0, errp);
413
+ if (!bs->file) {
233
if (ret < 0) {
414
+ return -EINVAL;
234
return ret;
415
+ }
235
}
416
+
236
diff --git a/blockdev.c b/blockdev.c
417
opts = qemu_opts_create(&vpc_runtime_opts, NULL, 0, &error_abort);
237
index XXXXXXX..XXXXXXX 100644
418
qemu_opts_absorb_qdict(opts, options, &local_err);
238
--- a/blockdev.c
419
if (local_err) {
239
+++ b/blockdev.c
420
diff --git a/tests/qemu-iotests/051.out b/tests/qemu-iotests/051.out
240
@@ -XXX,XX +XXX,XX @@ void qmp_block_resize(bool has_device, const char *device,
421
index XXXXXXX..XXXXXXX 100644
241
}
422
--- a/tests/qemu-iotests/051.out
242
423
+++ b/tests/qemu-iotests/051.out
243
bdrv_drained_begin(bs);
424
@@ -XXX,XX +XXX,XX @@ Testing: -drive driver=nbd
244
- ret = blk_truncate(blk, size, false, PREALLOC_MODE_OFF, errp);
425
QEMU_PROG: -drive driver=nbd: NBD server address missing
245
+ ret = blk_truncate(blk, size, false, PREALLOC_MODE_OFF, 0, errp);
426
246
bdrv_drained_end(bs);
427
Testing: -drive driver=raw
247
428
-QEMU_PROG: -drive driver=raw: Can't use 'raw' as a block driver for the protocol level
248
out:
429
+QEMU_PROG: -drive driver=raw: A block device must be specified for "file"
249
diff --git a/qemu-img.c b/qemu-img.c
430
250
index XXXXXXX..XXXXXXX 100644
431
Testing: -drive file.driver=file
251
--- a/qemu-img.c
432
QEMU_PROG: -drive file.driver=file: The 'file' block driver requires a file name
252
+++ b/qemu-img.c
433
@@ -XXX,XX +XXX,XX @@ Testing: -drive file.driver=nbd
253
@@ -XXX,XX +XXX,XX @@ static int img_resize(int argc, char **argv)
434
QEMU_PROG: -drive file.driver=nbd: NBD server address missing
254
* resizing, so pass @exact=true. It is of no use to report
435
255
* success when the image has not actually been resized.
436
Testing: -drive file.driver=raw
256
*/
437
-QEMU_PROG: -drive file.driver=raw: Can't use 'raw' as a block driver for the protocol level
257
- ret = blk_truncate(blk, total_size, true, prealloc, &err);
438
+QEMU_PROG: -drive file.driver=raw: A block device must be specified for "file"
258
+ ret = blk_truncate(blk, total_size, true, prealloc, 0, &err);
439
259
if (!ret) {
440
Testing: -drive foo=bar
260
qprintf(quiet, "Image resized.\n");
441
QEMU_PROG: -drive foo=bar: Must specify either driver or file
261
} else {
442
diff --git a/tests/qemu-iotests/051.pc.out b/tests/qemu-iotests/051.pc.out
262
diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
443
index XXXXXXX..XXXXXXX 100644
263
index XXXXXXX..XXXXXXX 100644
444
--- a/tests/qemu-iotests/051.pc.out
264
--- a/qemu-io-cmds.c
445
+++ b/tests/qemu-iotests/051.pc.out
265
+++ b/qemu-io-cmds.c
446
@@ -XXX,XX +XXX,XX @@ Testing: -drive driver=nbd
266
@@ -XXX,XX +XXX,XX @@ static int truncate_f(BlockBackend *blk, int argc, char **argv)
447
QEMU_PROG: -drive driver=nbd: NBD server address missing
267
* exact=true. It is better to err on the "emit more errors" side
448
268
* than to be overly permissive.
449
Testing: -drive driver=raw
269
*/
450
-QEMU_PROG: -drive driver=raw: Can't use 'raw' as a block driver for the protocol level
270
- ret = blk_truncate(blk, offset, true, PREALLOC_MODE_OFF, &local_err);
451
+QEMU_PROG: -drive driver=raw: A block device must be specified for "file"
271
+ ret = blk_truncate(blk, offset, true, PREALLOC_MODE_OFF, 0, &local_err);
452
272
if (ret < 0) {
453
Testing: -drive file.driver=file
273
error_report_err(local_err);
454
QEMU_PROG: -drive file.driver=file: The 'file' block driver requires a file name
274
return ret;
455
@@ -XXX,XX +XXX,XX @@ Testing: -drive file.driver=nbd
456
QEMU_PROG: -drive file.driver=nbd: NBD server address missing
457
458
Testing: -drive file.driver=raw
459
-QEMU_PROG: -drive file.driver=raw: Can't use 'raw' as a block driver for the protocol level
460
+QEMU_PROG: -drive file.driver=raw: A block device must be specified for "file"
461
462
Testing: -drive foo=bar
463
QEMU_PROG: -drive foo=bar: Must specify either driver or file
464
--
275
--
465
1.8.3.1
276
2.25.3
466
277
467
278
diff view generated by jsdifflib
1
This is more consistent with the commit block job, and it moves the code
1
If BDRV_REQ_ZERO_WRITE is set and we're extending the image, calling
2
to a place where we already have the necessary BlockBackends to resize
2
qcow2_cluster_zeroize() with flags=0 does the right thing: It doesn't
3
the base image when bdrv_truncate() is changed to require a BdrvChild.
3
undo any previous preallocation, but just adds the zero flag to all
4
relevant L2 entries. If an external data file is in use, a write_zeroes
5
request to the data file is made instead.
4
6
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
Message-Id: <20200424125448.63318-5-kwolf@redhat.com>
9
Reviewed-by: Eric Blake <eblake@redhat.com>
6
Reviewed-by: Max Reitz <mreitz@redhat.com>
10
Reviewed-by: Max Reitz <mreitz@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
---
12
---
8
block/mirror.c | 50 ++++++++++++++++++++++----------------------------
13
block/qcow2-cluster.c | 2 +-
9
1 file changed, 22 insertions(+), 28 deletions(-)
14
block/qcow2.c | 34 ++++++++++++++++++++++++++++++++++
15
2 files changed, 35 insertions(+), 1 deletion(-)
10
16
11
diff --git a/block/mirror.c b/block/mirror.c
17
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
12
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
13
--- a/block/mirror.c
19
--- a/block/qcow2-cluster.c
14
+++ b/block/mirror.c
20
+++ b/block/qcow2-cluster.c
15
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn mirror_run(void *opaque)
21
@@ -XXX,XX +XXX,XX @@ int qcow2_cluster_zeroize(BlockDriverState *bs, uint64_t offset,
16
if (s->bdev_length < 0) {
22
/* Caller must pass aligned values, except at image end */
17
ret = s->bdev_length;
23
assert(QEMU_IS_ALIGNED(offset, s->cluster_size));
18
goto immediate_exit;
24
assert(QEMU_IS_ALIGNED(end_offset, s->cluster_size) ||
19
- } else if (s->bdev_length == 0) {
25
- end_offset == bs->total_sectors << BDRV_SECTOR_BITS);
20
+ }
26
+ end_offset >= bs->total_sectors << BDRV_SECTOR_BITS);
27
28
/* The zero flag is only supported by version 3 and newer */
29
if (s->qcow_version < 3) {
30
diff --git a/block/qcow2.c b/block/qcow2.c
31
index XXXXXXX..XXXXXXX 100644
32
--- a/block/qcow2.c
33
+++ b/block/qcow2.c
34
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
35
36
bs->supported_zero_flags = header.version >= 3 ?
37
BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK : 0;
38
+ bs->supported_truncate_flags = BDRV_REQ_ZERO_WRITE;
39
40
/* Repair image if dirty */
41
if (!(flags & (BDRV_O_CHECK | BDRV_O_INACTIVE)) && !bs->read_only &&
42
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
43
g_assert_not_reached();
44
}
45
46
+ if ((flags & BDRV_REQ_ZERO_WRITE) && offset > old_length) {
47
+ uint64_t zero_start = QEMU_ALIGN_UP(old_length, s->cluster_size);
21
+
48
+
22
+ /* Active commit must resize the base image if its size differs from the
49
+ /*
23
+ * active layer. */
50
+ * Use zero clusters as much as we can. qcow2_cluster_zeroize()
24
+ if (s->base == blk_bs(s->target)) {
51
+ * requires a cluster-aligned start. The end may be unaligned if it is
25
+ int64_t base_length;
52
+ * at the end of the image (which it is here).
26
+
53
+ */
27
+ base_length = blk_getlength(s->target);
54
+ ret = qcow2_cluster_zeroize(bs, zero_start, offset - zero_start, 0);
28
+ if (base_length < 0) {
55
+ if (ret < 0) {
29
+ ret = base_length;
56
+ error_setg_errno(errp, -ret, "Failed to zero out new clusters");
30
+ goto immediate_exit;
57
+ goto fail;
31
+ }
58
+ }
32
+
59
+
33
+ if (s->bdev_length > base_length) {
60
+ /* Write explicit zeros for the unaligned head */
34
+ ret = blk_truncate(s->target, s->bdev_length);
61
+ if (zero_start > old_length) {
62
+ uint64_t len = zero_start - old_length;
63
+ uint8_t *buf = qemu_blockalign0(bs, len);
64
+ QEMUIOVector qiov;
65
+ qemu_iovec_init_buf(&qiov, buf, len);
66
+
67
+ qemu_co_mutex_unlock(&s->lock);
68
+ ret = qcow2_co_pwritev_part(bs, old_length, len, &qiov, 0, 0);
69
+ qemu_co_mutex_lock(&s->lock);
70
+
71
+ qemu_vfree(buf);
35
+ if (ret < 0) {
72
+ if (ret < 0) {
36
+ goto immediate_exit;
73
+ error_setg_errno(errp, -ret, "Failed to zero out the new area");
74
+ goto fail;
37
+ }
75
+ }
38
+ }
76
+ }
39
+ }
77
+ }
40
+
78
+
41
+ if (s->bdev_length == 0) {
79
if (prealloc != PREALLOC_MODE_OFF) {
42
/* Report BLOCK_JOB_READY and wait for complete. */
80
/* Flush metadata before actually changing the image size */
43
block_job_event_ready(&s->common);
81
ret = qcow2_write_caches(bs);
44
s->synced = true;
45
@@ -XXX,XX +XXX,XX @@ void commit_active_start(const char *job_id, BlockDriverState *bs,
46
BlockCompletionFunc *cb, void *opaque, Error **errp,
47
bool auto_complete)
48
{
49
- int64_t length, base_length;
50
int orig_base_flags;
51
- int ret;
52
Error *local_err = NULL;
53
54
orig_base_flags = bdrv_get_flags(base);
55
@@ -XXX,XX +XXX,XX @@ void commit_active_start(const char *job_id, BlockDriverState *bs,
56
return;
57
}
58
59
- length = bdrv_getlength(bs);
60
- if (length < 0) {
61
- error_setg_errno(errp, -length,
62
- "Unable to determine length of %s", bs->filename);
63
- goto error_restore_flags;
64
- }
65
-
66
- base_length = bdrv_getlength(base);
67
- if (base_length < 0) {
68
- error_setg_errno(errp, -base_length,
69
- "Unable to determine length of %s", base->filename);
70
- goto error_restore_flags;
71
- }
72
-
73
- if (length > base_length) {
74
- ret = bdrv_truncate(base, length);
75
- if (ret < 0) {
76
- error_setg_errno(errp, -ret,
77
- "Top image %s is larger than base image %s, and "
78
- "resize of base image failed",
79
- bs->filename, base->filename);
80
- goto error_restore_flags;
81
- }
82
- }
83
-
84
mirror_start_job(job_id, bs, creation_flags, base, NULL, speed, 0, 0,
85
MIRROR_LEAVE_BACKING_CHAIN,
86
on_error, on_error, true, cb, opaque, &local_err,
87
--
82
--
88
1.8.3.1
83
2.25.3
89
84
90
85
diff view generated by jsdifflib
1
This function allows to create more or less normal BlockDriverStates
1
The raw format driver can simply forward the flag and let its bs->file
2
even for BlockDrivers that aren't globally registered (e.g. helper
2
child take care of actually providing the zeros.
3
filters for block jobs).
4
3
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
Reviewed-by: Max Reitz <mreitz@redhat.com>
5
Reviewed-by: Max Reitz <mreitz@redhat.com>
6
Reviewed-by: Eric Blake <eblake@redhat.com>
7
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
8
Message-Id: <20200424125448.63318-6-kwolf@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
---
10
---
8
block.c | 30 +++++++++++++++++++++++++++++-
11
block/raw-format.c | 4 +++-
9
include/block/block.h | 2 ++
12
1 file changed, 3 insertions(+), 1 deletion(-)
10
2 files changed, 31 insertions(+), 1 deletion(-)
11
13
12
diff --git a/block.c b/block.c
14
diff --git a/block/raw-format.c b/block/raw-format.c
13
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
14
--- a/block.c
16
--- a/block/raw-format.c
15
+++ b/block.c
17
+++ b/block/raw-format.c
16
@@ -XXX,XX +XXX,XX @@ static int bdrv_open_driver(BlockDriverState *bs, BlockDriver *drv,
18
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset,
17
}
19
18
20
s->size = offset;
19
bs->drv = drv;
21
offset += s->offset;
20
+ bs->read_only = !(bs->open_flags & BDRV_O_RDWR);
22
- return bdrv_co_truncate(bs->file, offset, exact, prealloc, 0, errp);
21
bs->opaque = g_malloc0(drv->instance_size);
23
+ return bdrv_co_truncate(bs->file, offset, exact, prealloc, flags, errp);
22
23
if (drv->bdrv_file_open) {
24
assert(!drv->bdrv_needs_filename || bs->filename[0]);
25
ret = drv->bdrv_file_open(bs, options, open_flags, &local_err);
26
- } else {
27
+ } else if (drv->bdrv_open) {
28
ret = drv->bdrv_open(bs, options, open_flags, &local_err);
29
+ } else {
30
+ ret = 0;
31
}
32
33
if (ret < 0) {
34
@@ -XXX,XX +XXX,XX @@ free_and_fail:
35
return ret;
36
}
24
}
37
25
38
+BlockDriverState *bdrv_new_open_driver(BlockDriver *drv, const char *node_name,
26
static void raw_eject(BlockDriverState *bs, bool eject_flag)
39
+ int flags, Error **errp)
27
@@ -XXX,XX +XXX,XX @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags,
40
+{
28
bs->supported_zero_flags = BDRV_REQ_WRITE_UNCHANGED |
41
+ BlockDriverState *bs;
29
((BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK) &
42
+ int ret;
30
bs->file->bs->supported_zero_flags);
43
+
31
+ bs->supported_truncate_flags = bs->file->bs->supported_truncate_flags &
44
+ bs = bdrv_new();
32
+ BDRV_REQ_ZERO_WRITE;
45
+ bs->open_flags = flags;
33
46
+ bs->explicit_options = qdict_new();
34
if (bs->probed && !bdrv_is_read_only(bs)) {
47
+ bs->options = qdict_new();
35
bdrv_refresh_filename(bs->file->bs);
48
+ bs->opaque = NULL;
49
+
50
+ update_options_from_flags(bs->options, flags);
51
+
52
+ ret = bdrv_open_driver(bs, drv, node_name, bs->options, flags, errp);
53
+ if (ret < 0) {
54
+ QDECREF(bs->explicit_options);
55
+ QDECREF(bs->options);
56
+ bdrv_unref(bs);
57
+ return NULL;
58
+ }
59
+
60
+ return bs;
61
+}
62
+
63
QemuOptsList bdrv_runtime_opts = {
64
.name = "bdrv_common",
65
.head = QTAILQ_HEAD_INITIALIZER(bdrv_runtime_opts.head),
66
diff --git a/include/block/block.h b/include/block/block.h
67
index XXXXXXX..XXXXXXX 100644
68
--- a/include/block/block.h
69
+++ b/include/block/block.h
70
@@ -XXX,XX +XXX,XX @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options,
71
const char *bdref_key, Error **errp);
72
BlockDriverState *bdrv_open(const char *filename, const char *reference,
73
QDict *options, int flags, Error **errp);
74
+BlockDriverState *bdrv_new_open_driver(BlockDriver *drv, const char *node_name,
75
+ int flags, Error **errp);
76
BlockReopenQueue *bdrv_reopen_queue(BlockReopenQueue *bs_queue,
77
BlockDriverState *bs,
78
QDict *options, int flags);
79
--
36
--
80
1.8.3.1
37
2.25.3
81
38
82
39
diff view generated by jsdifflib
1
From: Nir Soffer <nirsof@gmail.com>
1
For regular files, we always get BDRV_REQ_ZERO_WRITE behaviour from the
2
OS, so we can advertise the flag and just ignore it.
2
3
3
Now that we are truncating the file in both PREALLOC_MODE_FULL and
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
PREALLOC_MODE_OFF, not truncating in PREALLOC_MODE_FALLOC looks odd.
5
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
5
Add a comment explaining why we do not truncate in this case.
6
Reviewed-by: Alberto Garcia <berto@igalia.com>
6
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
7
Signed-off-by: Nir Soffer <nirsof@gmail.com>
8
Message-Id: <20200424125448.63318-7-kwolf@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
10
---
10
block/file-posix.c | 7 ++++++-
11
block/file-posix.c | 4 ++++
11
1 file changed, 6 insertions(+), 1 deletion(-)
12
1 file changed, 4 insertions(+)
12
13
13
diff --git a/block/file-posix.c b/block/file-posix.c
14
diff --git a/block/file-posix.c b/block/file-posix.c
14
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
15
--- a/block/file-posix.c
16
--- a/block/file-posix.c
16
+++ b/block/file-posix.c
17
+++ b/block/file-posix.c
17
@@ -XXX,XX +XXX,XX @@ static int raw_create(const char *filename, QemuOpts *opts, Error **errp)
18
@@ -XXX,XX +XXX,XX @@ static int raw_open_common(BlockDriverState *bs, QDict *options,
18
switch (prealloc) {
19
#endif
19
#ifdef CONFIG_POSIX_FALLOCATE
20
20
case PREALLOC_MODE_FALLOC:
21
bs->supported_zero_flags = BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK;
21
- /* posix_fallocate() doesn't set errno. */
22
+ if (S_ISREG(st.st_mode)) {
22
+ /*
23
+ /* When extending regular files, we get zeros from the OS */
23
+ * Truncating before posix_fallocate() makes it about twice slower on
24
+ bs->supported_truncate_flags = BDRV_REQ_ZERO_WRITE;
24
+ * file systems that do not support fallocate(), trying to check if a
25
+ }
25
+ * block is allocated before allocating it, so don't do that here.
26
ret = 0;
26
+ */
27
fail:
27
result = -posix_fallocate(fd, 0, total_size);
28
if (filename && (bdrv_flags & BDRV_O_TEMPORARY)) {
28
if (result != 0) {
29
+ /* posix_fallocate() doesn't set errno. */
30
error_setg_errno(errp, -result,
31
"Could not preallocate data for the new file");
32
}
33
--
29
--
34
1.8.3.1
30
2.25.3
35
31
36
32
diff view generated by jsdifflib
1
In order to be able to do permission checking and to keep working with
1
When extending the size of an image that has a backing file larger than
2
the BdrvChild based bdrv_truncate() that this involves, we need to
2
its old size, make sure that the backing file data doesn't become
3
create a temporary BlockBackend to resize the image.
3
visible in the guest, but the added area is properly zeroed out.
4
5
Consider the following scenario where the overlay is shorter than its
6
backing file:
7
8
base.qcow2: AAAAAAAA
9
overlay.qcow2: BBBB
10
11
When resizing (extending) overlay.qcow2, the new blocks should not stay
12
unallocated and make the additional As from base.qcow2 visible like
13
before this patch, but zeros should be read.
14
15
A similar case happens with the various variants of a commit job when an
16
intermediate file is short (- for unallocated):
17
18
base.qcow2: A-A-AAAA
19
mid.qcow2: BB-B
20
top.qcow2: C--C--C-
21
22
After commit top.qcow2 to mid.qcow2, the following happens:
23
24
mid.qcow2: CB-C00C0 (correct result)
25
mid.qcow2: CB-C--C- (before this fix)
26
27
Without the fix, blocks that previously read as zeros on top.qcow2
28
suddenly turn into A.
4
29
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
30
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
31
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
32
Message-Id: <20200424125448.63318-8-kwolf@redhat.com>
6
Reviewed-by: Max Reitz <mreitz@redhat.com>
33
Reviewed-by: Max Reitz <mreitz@redhat.com>
34
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
---
35
---
8
blockdev.c | 7 ++++++-
36
block/io.c | 25 +++++++++++++++++++++++++
9
1 file changed, 6 insertions(+), 1 deletion(-)
37
1 file changed, 25 insertions(+)
10
38
11
diff --git a/blockdev.c b/blockdev.c
39
diff --git a/block/io.c b/block/io.c
12
index XXXXXXX..XXXXXXX 100644
40
index XXXXXXX..XXXXXXX 100644
13
--- a/blockdev.c
41
--- a/block/io.c
14
+++ b/blockdev.c
42
+++ b/block/io.c
15
@@ -XXX,XX +XXX,XX @@ void qmp_block_resize(bool has_device, const char *device,
43
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
16
int64_t size, Error **errp)
17
{
18
Error *local_err = NULL;
19
+ BlockBackend *blk = NULL;
20
BlockDriverState *bs;
21
AioContext *aio_context;
22
int ret;
23
@@ -XXX,XX +XXX,XX @@ void qmp_block_resize(bool has_device, const char *device,
24
goto out;
44
goto out;
25
}
45
}
26
46
27
+ blk = blk_new();
47
+ /*
28
+ blk_insert_bs(blk, bs);
48
+ * If the image has a backing file that is large enough that it would
49
+ * provide data for the new area, we cannot leave it unallocated because
50
+ * then the backing file content would become visible. Instead, zero-fill
51
+ * the new area.
52
+ *
53
+ * Note that if the image has a backing file, but was opened without the
54
+ * backing file, taking care of keeping things consistent with that backing
55
+ * file is the user's responsibility.
56
+ */
57
+ if (new_bytes && bs->backing) {
58
+ int64_t backing_len;
29
+
59
+
30
/* complete all in-flight operations before resizing the device */
60
+ backing_len = bdrv_getlength(backing_bs(bs));
31
bdrv_drain_all();
61
+ if (backing_len < 0) {
32
62
+ ret = backing_len;
33
- ret = bdrv_truncate(bs, size);
63
+ error_setg_errno(errp, -ret, "Could not get backing file size");
34
+ ret = blk_truncate(blk, size);
64
+ goto out;
35
switch (ret) {
65
+ }
36
case 0:
66
+
37
break;
67
+ if (backing_len > old_size) {
38
@@ -XXX,XX +XXX,XX @@ void qmp_block_resize(bool has_device, const char *device,
68
+ flags |= BDRV_REQ_ZERO_WRITE;
39
}
69
+ }
40
70
+ }
41
out:
71
+
42
+ blk_unref(blk);
72
if (drv->bdrv_co_truncate) {
43
aio_context_release(aio_context);
73
if (flags & ~bs->supported_truncate_flags) {
44
}
74
error_setg(errp, "Block driver does not support requested flags");
45
46
--
75
--
47
1.8.3.1
76
2.25.3
48
77
49
78
diff view generated by jsdifflib
1
blk_insert_bs() and block job related functions will soon require an
1
We want to keep TEST_IMG for the full path of the main test image, but
2
opened block node (permission calculations will involve the block
2
filter_testfiles() must be called for other test images before replacing
3
driver), so let our tests be consistent with the real users in this
3
other things like the image format because the test directory path could
4
respect.
4
contain the format as a substring.
5
6
Insert a filter_testfiles() call between both.
5
7
6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
9
Reviewed-by: Max Reitz <mreitz@redhat.com>
10
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
11
Message-Id: <20200424125448.63318-9-kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
---
13
---
9
tests/test-blockjob-txn.c | 6 +++++-
14
tests/qemu-iotests/iotests.py | 5 +++--
10
tests/test-blockjob.c | 6 +++++-
15
1 file changed, 3 insertions(+), 2 deletions(-)
11
2 files changed, 10 insertions(+), 2 deletions(-)
12
16
13
diff --git a/tests/test-blockjob-txn.c b/tests/test-blockjob-txn.c
17
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
14
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
15
--- a/tests/test-blockjob-txn.c
19
--- a/tests/qemu-iotests/iotests.py
16
+++ b/tests/test-blockjob-txn.c
20
+++ b/tests/qemu-iotests/iotests.py
17
@@ -XXX,XX +XXX,XX @@ static BlockJob *test_block_job_start(unsigned int iterations,
21
@@ -XXX,XX +XXX,XX @@ def filter_img_info(output, filename):
18
char job_id[24];
22
for line in output.split('\n'):
19
23
if 'disk size' in line or 'actual-size' in line:
20
data = g_new0(TestBlockJobCBData, 1);
24
continue
21
- bs = bdrv_new();
25
- line = line.replace(filename, 'TEST_IMG') \
22
+
26
- .replace(imgfmt, 'IMGFMT')
23
+ bs = bdrv_open("null-co://", NULL, NULL, 0, &error_abort);
27
+ line = line.replace(filename, 'TEST_IMG')
24
+ g_assert_nonnull(bs);
28
+ line = filter_testfiles(line)
25
+
29
+ line = line.replace(imgfmt, 'IMGFMT')
26
snprintf(job_id, sizeof(job_id), "job%u", counter++);
30
line = re.sub('iters: [0-9]+', 'iters: XXX', line)
27
s = block_job_create(job_id, &test_block_job_driver, bs, 0,
31
line = re.sub('uuid: [-a-f0-9]+', 'uuid: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX', line)
28
BLOCK_JOB_DEFAULT, test_block_job_cb,
32
line = re.sub('cid: [0-9]+', 'cid: XXXXXXXXXX', line)
29
@@ -XXX,XX +XXX,XX @@ static void test_pair_jobs_fail_cancel_race(void)
30
int main(int argc, char **argv)
31
{
32
qemu_init_main_loop(&error_abort);
33
+ bdrv_init();
34
35
g_test_init(&argc, &argv, NULL);
36
g_test_add_func("/single/success", test_single_job_success);
37
diff --git a/tests/test-blockjob.c b/tests/test-blockjob.c
38
index XXXXXXX..XXXXXXX 100644
39
--- a/tests/test-blockjob.c
40
+++ b/tests/test-blockjob.c
41
@@ -XXX,XX +XXX,XX @@ static BlockJob *do_test_id(BlockBackend *blk, const char *id,
42
static BlockBackend *create_blk(const char *name)
43
{
44
BlockBackend *blk = blk_new();
45
- BlockDriverState *bs = bdrv_new();
46
+ BlockDriverState *bs;
47
+
48
+ bs = bdrv_open("null-co://", NULL, NULL, 0, &error_abort);
49
+ g_assert_nonnull(bs);
50
51
blk_insert_bs(blk, bs);
52
bdrv_unref(bs);
53
@@ -XXX,XX +XXX,XX @@ static void test_job_ids(void)
54
int main(int argc, char **argv)
55
{
56
qemu_init_main_loop(&error_abort);
57
+ bdrv_init();
58
59
g_test_init(&argc, &argv, NULL);
60
g_test_add_func("/blockjob/ids", test_job_ids);
61
--
33
--
62
1.8.3.1
34
2.25.3
63
35
64
36
diff view generated by jsdifflib
1
From: Nir Soffer <nirsof@gmail.com>
1
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2
2
Message-Id: <20200424125448.63318-10-kwolf@redhat.com>
3
Add tests for creating raw image with and without the preallocation
3
Reviewed-by: Max Reitz <mreitz@redhat.com>
4
option.
4
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
5
6
Signed-off-by: Nir Soffer <nirsof@gmail.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
---
6
---
9
tests/qemu-iotests/175 | 61 ++++++++++++++++++++++++++++++++++++++++++++++
7
tests/qemu-iotests/274 | 155 +++++++++++++++++++++
10
tests/qemu-iotests/175.out | 18 ++++++++++++++
8
tests/qemu-iotests/274.out | 268 +++++++++++++++++++++++++++++++++++++
11
tests/qemu-iotests/group | 1 +
9
tests/qemu-iotests/group | 1 +
12
3 files changed, 80 insertions(+)
10
3 files changed, 424 insertions(+)
13
create mode 100755 tests/qemu-iotests/175
11
create mode 100755 tests/qemu-iotests/274
14
create mode 100644 tests/qemu-iotests/175.out
12
create mode 100644 tests/qemu-iotests/274.out
15
13
16
diff --git a/tests/qemu-iotests/175 b/tests/qemu-iotests/175
14
diff --git a/tests/qemu-iotests/274 b/tests/qemu-iotests/274
17
new file mode 100755
15
new file mode 100755
18
index XXXXXXX..XXXXXXX
16
index XXXXXXX..XXXXXXX
19
--- /dev/null
17
--- /dev/null
20
+++ b/tests/qemu-iotests/175
18
+++ b/tests/qemu-iotests/274
21
@@ -XXX,XX +XXX,XX @@
19
@@ -XXX,XX +XXX,XX @@
22
+#!/bin/bash
20
+#!/usr/bin/env python3
23
+#
21
+#
24
+# Test creating raw image preallocation mode
22
+# Copyright (C) 2019 Red Hat, Inc.
25
+#
26
+# Copyright (C) 2017 Nir Soffer <nirsof@gmail.com>
27
+#
23
+#
28
+# This program is free software; you can redistribute it and/or modify
24
+# This program is free software; you can redistribute it and/or modify
29
+# it under the terms of the GNU General Public License as published by
25
+# it under the terms of the GNU General Public License as published by
30
+# the Free Software Foundation; either version 2 of the License, or
26
+# the Free Software Foundation; either version 2 of the License, or
31
+# (at your option) any later version.
27
+# (at your option) any later version.
...
...
36
+# GNU General Public License for more details.
32
+# GNU General Public License for more details.
37
+#
33
+#
38
+# You should have received a copy of the GNU General Public License
34
+# You should have received a copy of the GNU General Public License
39
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
35
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
40
+#
36
+#
41
+
37
+# Creator/Owner: Kevin Wolf <kwolf@redhat.com>
42
+# creator
38
+#
43
+owner=nirsof@gmail.com
39
+# Some tests for short backing files and short overlays
44
+
40
+
45
+seq=`basename $0`
41
+import iotests
46
+echo "QA output created by $seq"
42
+
47
+
43
+iotests.verify_image_format(supported_fmts=['qcow2'])
48
+here=`pwd`
44
+iotests.verify_platform(['linux'])
49
+status=1    # failure is the default!
45
+
50
+
46
+size_short = 1 * 1024 * 1024
51
+_cleanup()
47
+size_long = 2 * 1024 * 1024
52
+{
48
+size_diff = size_long - size_short
53
+    _cleanup_test_img
49
+
54
+}
50
+def create_chain() -> None:
55
+trap "_cleanup; exit \$status" 0 1 2 3 15
51
+ iotests.qemu_img_log('create', '-f', iotests.imgfmt, base,
56
+
52
+ str(size_long))
57
+# get standard environment, filters and checks
53
+ iotests.qemu_img_log('create', '-f', iotests.imgfmt, '-b', base, mid,
58
+. ./common.rc
54
+ str(size_short))
59
+. ./common.filter
55
+ iotests.qemu_img_log('create', '-f', iotests.imgfmt, '-b', mid, top,
60
+
56
+ str(size_long))
61
+_supported_fmt raw
57
+
62
+_supported_proto file
58
+ iotests.qemu_io_log('-c', 'write -P 1 0 %d' % size_long, base)
63
+_supported_os Linux
59
+
64
+
60
+def create_vm() -> iotests.VM:
65
+size=1m
61
+ vm = iotests.VM()
66
+
62
+ vm.add_blockdev('file,filename=%s,node-name=base-file' % base)
67
+echo
63
+ vm.add_blockdev('%s,file=base-file,node-name=base' % iotests.imgfmt)
68
+echo "== creating image with default preallocation =="
64
+ vm.add_blockdev('file,filename=%s,node-name=mid-file' % mid)
69
+_make_test_img $size | _filter_imgfmt
65
+ vm.add_blockdev('%s,file=mid-file,node-name=mid,backing=base'
70
+stat -c "size=%s, blocks=%b" $TEST_IMG
66
+ % iotests.imgfmt)
71
+
67
+ vm.add_drive(top, 'backing=mid,node-name=top')
72
+for mode in off full falloc; do
68
+ return vm
73
+ echo
69
+
74
+ echo "== creating image with preallocation $mode =="
70
+with iotests.FilePath('base') as base, \
75
+ IMGOPTS=preallocation=$mode _make_test_img $size | _filter_imgfmt
71
+ iotests.FilePath('mid') as mid, \
76
+ stat -c "size=%s, blocks=%b" $TEST_IMG
72
+ iotests.FilePath('top') as top:
77
+done
73
+
78
+
74
+ iotests.log('== Commit tests ==')
79
+# success, all done
75
+
80
+echo "*** done"
76
+ create_chain()
81
+rm -f $seq.full
77
+
82
+status=0
78
+ iotests.log('=== Check visible data ===')
83
diff --git a/tests/qemu-iotests/175.out b/tests/qemu-iotests/175.out
79
+
80
+ iotests.qemu_io_log('-c', 'read -P 1 0 %d' % size_short, top)
81
+ iotests.qemu_io_log('-c', 'read -P 0 %d %d' % (size_short, size_diff), top)
82
+
83
+ iotests.log('=== Checking allocation status ===')
84
+
85
+ iotests.qemu_io_log('-c', 'alloc 0 %d' % size_short,
86
+ '-c', 'alloc %d %d' % (size_short, size_diff),
87
+ base)
88
+
89
+ iotests.qemu_io_log('-c', 'alloc 0 %d' % size_short,
90
+ '-c', 'alloc %d %d' % (size_short, size_diff),
91
+ mid)
92
+
93
+ iotests.qemu_io_log('-c', 'alloc 0 %d' % size_short,
94
+ '-c', 'alloc %d %d' % (size_short, size_diff),
95
+ top)
96
+
97
+ iotests.log('=== Checking map ===')
98
+
99
+ iotests.qemu_img_log('map', '--output=json', base)
100
+ iotests.qemu_img_log('map', '--output=human', base)
101
+ iotests.qemu_img_log('map', '--output=json', mid)
102
+ iotests.qemu_img_log('map', '--output=human', mid)
103
+ iotests.qemu_img_log('map', '--output=json', top)
104
+ iotests.qemu_img_log('map', '--output=human', top)
105
+
106
+ iotests.log('=== Testing qemu-img commit (top -> mid) ===')
107
+
108
+ iotests.qemu_img_log('commit', top)
109
+ iotests.img_info_log(mid)
110
+ iotests.qemu_io_log('-c', 'read -P 1 0 %d' % size_short, mid)
111
+ iotests.qemu_io_log('-c', 'read -P 0 %d %d' % (size_short, size_diff), mid)
112
+
113
+ iotests.log('=== Testing HMP commit (top -> mid) ===')
114
+
115
+ create_chain()
116
+ with create_vm() as vm:
117
+ vm.launch()
118
+ vm.qmp_log('human-monitor-command', command_line='commit drive0')
119
+
120
+ iotests.img_info_log(mid)
121
+ iotests.qemu_io_log('-c', 'read -P 1 0 %d' % size_short, mid)
122
+ iotests.qemu_io_log('-c', 'read -P 0 %d %d' % (size_short, size_diff), mid)
123
+
124
+ iotests.log('=== Testing QMP active commit (top -> mid) ===')
125
+
126
+ create_chain()
127
+ with create_vm() as vm:
128
+ vm.launch()
129
+ vm.qmp_log('block-commit', device='top', base_node='mid',
130
+ job_id='job0', auto_dismiss=False)
131
+ vm.run_job('job0', wait=5)
132
+
133
+ iotests.img_info_log(mid)
134
+ iotests.qemu_io_log('-c', 'read -P 1 0 %d' % size_short, mid)
135
+ iotests.qemu_io_log('-c', 'read -P 0 %d %d' % (size_short, size_diff), mid)
136
+
137
+
138
+ iotests.log('== Resize tests ==')
139
+
140
+ # Use different sizes for different allocation modes:
141
+ #
142
+ # We want to have at least one test where 32 bit truncation in the size of
143
+ # the overlapping area becomes visible. This is covered by the
144
+ # prealloc='off' case (1G to 6G is an overlap of 5G).
145
+ #
146
+ # However, we can only do this for modes that don't preallocate data
147
+ # because otherwise we might run out of space on the test host.
148
+ #
149
+ # We also want to test some unaligned combinations.
150
+ for (prealloc, base_size, top_size_old, top_size_new, off) in [
151
+ ('off', '6G', '1G', '8G', '5G'),
152
+ ('metadata', '32G', '30G', '33G', '31G'),
153
+ ('falloc', '10M', '5M', '15M', '9M'),
154
+ ('full', '16M', '8M', '12M', '11M'),
155
+ ('off', '384k', '253k', '512k', '253k'),
156
+ ('off', '400k', '256k', '512k', '336k'),
157
+ ('off', '512k', '256k', '500k', '436k')]:
158
+
159
+ iotests.log('=== preallocation=%s ===' % prealloc)
160
+ iotests.qemu_img_log('create', '-f', iotests.imgfmt, base, base_size)
161
+ iotests.qemu_img_log('create', '-f', iotests.imgfmt, '-b', base, top,
162
+ top_size_old)
163
+ iotests.qemu_io_log('-c', 'write -P 1 %s 64k' % off, base)
164
+
165
+ # After this, top_size_old to base_size should be allocated/zeroed.
166
+ #
167
+ # In theory, leaving base_size to top_size_new unallocated would be
168
+ # correct, but in practice, if we zero out anything, we zero out
169
+ # everything up to top_size_new.
170
+ iotests.qemu_img_log('resize', '-f', iotests.imgfmt,
171
+ '--preallocation', prealloc, top, top_size_new)
172
+ iotests.qemu_io_log('-c', 'read -P 0 %s 64k' % off, top)
173
+ iotests.qemu_io_log('-c', 'map', top)
174
+ iotests.qemu_img_log('map', '--output=json', top)
175
diff --git a/tests/qemu-iotests/274.out b/tests/qemu-iotests/274.out
84
new file mode 100644
176
new file mode 100644
85
index XXXXXXX..XXXXXXX
177
index XXXXXXX..XXXXXXX
86
--- /dev/null
178
--- /dev/null
87
+++ b/tests/qemu-iotests/175.out
179
+++ b/tests/qemu-iotests/274.out
88
@@ -XXX,XX +XXX,XX @@
180
@@ -XXX,XX +XXX,XX @@
89
+QA output created by 175
181
+== Commit tests ==
90
+
182
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=2097152 cluster_size=65536 lazy_refcounts=off refcount_bits=16
91
+== creating image with default preallocation ==
183
+
92
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
184
+Formatting 'TEST_DIR/PID-mid', fmt=qcow2 size=1048576 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
93
+size=1048576, blocks=0
185
+
94
+
186
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=2097152 backing_file=TEST_DIR/PID-mid cluster_size=65536 lazy_refcounts=off refcount_bits=16
95
+== creating image with preallocation off ==
187
+
96
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 preallocation=off
188
+wrote 2097152/2097152 bytes at offset 0
97
+size=1048576, blocks=0
189
+2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
98
+
190
+
99
+== creating image with preallocation full ==
191
+=== Check visible data ===
100
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 preallocation=full
192
+read 1048576/1048576 bytes at offset 0
101
+size=1048576, blocks=2048
193
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
102
+
194
+
103
+== creating image with preallocation falloc ==
195
+read 1048576/1048576 bytes at offset 1048576
104
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 preallocation=falloc
196
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
105
+size=1048576, blocks=2048
197
+
106
+ *** done
198
+=== Checking allocation status ===
199
+1048576/1048576 bytes allocated at offset 0 bytes
200
+1048576/1048576 bytes allocated at offset 1 MiB
201
+
202
+0/1048576 bytes allocated at offset 0 bytes
203
+0/0 bytes allocated at offset 1 MiB
204
+
205
+0/1048576 bytes allocated at offset 0 bytes
206
+0/1048576 bytes allocated at offset 1 MiB
207
+
208
+=== Checking map ===
209
+[{ "start": 0, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": 327680}]
210
+
211
+Offset Length Mapped to File
212
+0 0x200000 0x50000 TEST_DIR/PID-base
213
+
214
+[{ "start": 0, "length": 1048576, "depth": 1, "zero": false, "data": true, "offset": 327680}]
215
+
216
+Offset Length Mapped to File
217
+0 0x100000 0x50000 TEST_DIR/PID-base
218
+
219
+[{ "start": 0, "length": 1048576, "depth": 2, "zero": false, "data": true, "offset": 327680},
220
+{ "start": 1048576, "length": 1048576, "depth": 0, "zero": true, "data": false}]
221
+
222
+Offset Length Mapped to File
223
+0 0x100000 0x50000 TEST_DIR/PID-base
224
+
225
+=== Testing qemu-img commit (top -> mid) ===
226
+Image committed.
227
+
228
+image: TEST_IMG
229
+file format: IMGFMT
230
+virtual size: 2 MiB (2097152 bytes)
231
+cluster_size: 65536
232
+backing file: TEST_DIR/PID-base
233
+Format specific information:
234
+ compat: 1.1
235
+ lazy refcounts: false
236
+ refcount bits: 16
237
+ corrupt: false
238
+
239
+read 1048576/1048576 bytes at offset 0
240
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
241
+
242
+read 1048576/1048576 bytes at offset 1048576
243
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
244
+
245
+=== Testing HMP commit (top -> mid) ===
246
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=2097152 cluster_size=65536 lazy_refcounts=off refcount_bits=16
247
+
248
+Formatting 'TEST_DIR/PID-mid', fmt=qcow2 size=1048576 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
249
+
250
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=2097152 backing_file=TEST_DIR/PID-mid cluster_size=65536 lazy_refcounts=off refcount_bits=16
251
+
252
+wrote 2097152/2097152 bytes at offset 0
253
+2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
254
+
255
+{"execute": "human-monitor-command", "arguments": {"command-line": "commit drive0"}}
256
+{"return": ""}
257
+image: TEST_IMG
258
+file format: IMGFMT
259
+virtual size: 2 MiB (2097152 bytes)
260
+cluster_size: 65536
261
+backing file: TEST_DIR/PID-base
262
+Format specific information:
263
+ compat: 1.1
264
+ lazy refcounts: false
265
+ refcount bits: 16
266
+ corrupt: false
267
+
268
+read 1048576/1048576 bytes at offset 0
269
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
270
+
271
+read 1048576/1048576 bytes at offset 1048576
272
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
273
+
274
+=== Testing QMP active commit (top -> mid) ===
275
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=2097152 cluster_size=65536 lazy_refcounts=off refcount_bits=16
276
+
277
+Formatting 'TEST_DIR/PID-mid', fmt=qcow2 size=1048576 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
278
+
279
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=2097152 backing_file=TEST_DIR/PID-mid cluster_size=65536 lazy_refcounts=off refcount_bits=16
280
+
281
+wrote 2097152/2097152 bytes at offset 0
282
+2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
283
+
284
+{"execute": "block-commit", "arguments": {"auto-dismiss": false, "base-node": "mid", "device": "top", "job-id": "job0"}}
285
+{"return": {}}
286
+{"execute": "job-complete", "arguments": {"id": "job0"}}
287
+{"return": {}}
288
+{"data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "commit"}, "event": "BLOCK_JOB_READY", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
289
+{"data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "commit"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
290
+{"execute": "job-dismiss", "arguments": {"id": "job0"}}
291
+{"return": {}}
292
+image: TEST_IMG
293
+file format: IMGFMT
294
+virtual size: 2 MiB (2097152 bytes)
295
+cluster_size: 65536
296
+backing file: TEST_DIR/PID-base
297
+Format specific information:
298
+ compat: 1.1
299
+ lazy refcounts: false
300
+ refcount bits: 16
301
+ corrupt: false
302
+
303
+read 1048576/1048576 bytes at offset 0
304
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
305
+
306
+read 1048576/1048576 bytes at offset 1048576
307
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
308
+
309
+== Resize tests ==
310
+=== preallocation=off ===
311
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=6442450944 cluster_size=65536 lazy_refcounts=off refcount_bits=16
312
+
313
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=1073741824 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
314
+
315
+wrote 65536/65536 bytes at offset 5368709120
316
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
317
+
318
+Image resized.
319
+
320
+read 65536/65536 bytes at offset 5368709120
321
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
322
+
323
+1 GiB (0x40000000) bytes not allocated at offset 0 bytes (0x0)
324
+7 GiB (0x1c0000000) bytes allocated at offset 1 GiB (0x40000000)
325
+
326
+[{ "start": 0, "length": 1073741824, "depth": 1, "zero": true, "data": false},
327
+{ "start": 1073741824, "length": 7516192768, "depth": 0, "zero": true, "data": false}]
328
+
329
+=== preallocation=metadata ===
330
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=34359738368 cluster_size=65536 lazy_refcounts=off refcount_bits=16
331
+
332
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=32212254720 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
333
+
334
+wrote 65536/65536 bytes at offset 33285996544
335
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
336
+
337
+Image resized.
338
+
339
+read 65536/65536 bytes at offset 33285996544
340
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
341
+
342
+30 GiB (0x780000000) bytes not allocated at offset 0 bytes (0x0)
343
+3 GiB (0xc0000000) bytes allocated at offset 30 GiB (0x780000000)
344
+
345
+[{ "start": 0, "length": 32212254720, "depth": 1, "zero": true, "data": false},
346
+{ "start": 32212254720, "length": 536870912, "depth": 0, "zero": true, "data": false, "offset": 327680},
347
+{ "start": 32749125632, "length": 536870912, "depth": 0, "zero": true, "data": false, "offset": 537264128},
348
+{ "start": 33285996544, "length": 536870912, "depth": 0, "zero": true, "data": false, "offset": 1074200576},
349
+{ "start": 33822867456, "length": 536870912, "depth": 0, "zero": true, "data": false, "offset": 1611137024},
350
+{ "start": 34359738368, "length": 536870912, "depth": 0, "zero": true, "data": false, "offset": 2148139008},
351
+{ "start": 34896609280, "length": 536870912, "depth": 0, "zero": true, "data": false, "offset": 2685075456}]
352
+
353
+=== preallocation=falloc ===
354
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=10485760 cluster_size=65536 lazy_refcounts=off refcount_bits=16
355
+
356
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=5242880 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
357
+
358
+wrote 65536/65536 bytes at offset 9437184
359
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
360
+
361
+Image resized.
362
+
363
+read 65536/65536 bytes at offset 9437184
364
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
365
+
366
+5 MiB (0x500000) bytes not allocated at offset 0 bytes (0x0)
367
+10 MiB (0xa00000) bytes allocated at offset 5 MiB (0x500000)
368
+
369
+[{ "start": 0, "length": 5242880, "depth": 1, "zero": true, "data": false},
370
+{ "start": 5242880, "length": 10485760, "depth": 0, "zero": true, "data": false, "offset": 327680}]
371
+
372
+=== preallocation=full ===
373
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=16777216 cluster_size=65536 lazy_refcounts=off refcount_bits=16
374
+
375
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=8388608 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
376
+
377
+wrote 65536/65536 bytes at offset 11534336
378
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
379
+
380
+Image resized.
381
+
382
+read 65536/65536 bytes at offset 11534336
383
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
384
+
385
+8 MiB (0x800000) bytes not allocated at offset 0 bytes (0x0)
386
+4 MiB (0x400000) bytes allocated at offset 8 MiB (0x800000)
387
+
388
+[{ "start": 0, "length": 8388608, "depth": 1, "zero": true, "data": false},
389
+{ "start": 8388608, "length": 4194304, "depth": 0, "zero": true, "data": false, "offset": 327680}]
390
+
391
+=== preallocation=off ===
392
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=393216 cluster_size=65536 lazy_refcounts=off refcount_bits=16
393
+
394
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=259072 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
395
+
396
+wrote 65536/65536 bytes at offset 259072
397
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
398
+
399
+Image resized.
400
+
401
+read 65536/65536 bytes at offset 259072
402
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
403
+
404
+192 KiB (0x30000) bytes not allocated at offset 0 bytes (0x0)
405
+320 KiB (0x50000) bytes allocated at offset 192 KiB (0x30000)
406
+
407
+[{ "start": 0, "length": 196608, "depth": 1, "zero": true, "data": false},
408
+{ "start": 196608, "length": 65536, "depth": 0, "zero": false, "data": true, "offset": 327680},
409
+{ "start": 262144, "length": 262144, "depth": 0, "zero": true, "data": false}]
410
+
411
+=== preallocation=off ===
412
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=409600 cluster_size=65536 lazy_refcounts=off refcount_bits=16
413
+
414
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=262144 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
415
+
416
+wrote 65536/65536 bytes at offset 344064
417
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
418
+
419
+Image resized.
420
+
421
+read 65536/65536 bytes at offset 344064
422
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
423
+
424
+256 KiB (0x40000) bytes not allocated at offset 0 bytes (0x0)
425
+256 KiB (0x40000) bytes allocated at offset 256 KiB (0x40000)
426
+
427
+[{ "start": 0, "length": 262144, "depth": 1, "zero": true, "data": false},
428
+{ "start": 262144, "length": 262144, "depth": 0, "zero": true, "data": false}]
429
+
430
+=== preallocation=off ===
431
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=524288 cluster_size=65536 lazy_refcounts=off refcount_bits=16
432
+
433
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=262144 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
434
+
435
+wrote 65536/65536 bytes at offset 446464
436
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
437
+
438
+Image resized.
439
+
440
+read 65536/65536 bytes at offset 446464
441
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
442
+
443
+256 KiB (0x40000) bytes not allocated at offset 0 bytes (0x0)
444
+244 KiB (0x3d000) bytes allocated at offset 256 KiB (0x40000)
445
+
446
+[{ "start": 0, "length": 262144, "depth": 1, "zero": true, "data": false},
447
+{ "start": 262144, "length": 249856, "depth": 0, "zero": true, "data": false}]
448
+
107
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
449
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
108
index XXXXXXX..XXXXXXX 100644
450
index XXXXXXX..XXXXXXX 100644
109
--- a/tests/qemu-iotests/group
451
--- a/tests/qemu-iotests/group
110
+++ b/tests/qemu-iotests/group
452
+++ b/tests/qemu-iotests/group
111
@@ -XXX,XX +XXX,XX @@
453
@@ -XXX,XX +XXX,XX @@
112
172 auto
454
270 rw backing quick
113
173 rw auto
455
272 rw
114
174 auto
456
273 backing quick
115
+175 auto quick
457
+274 rw backing
458
277 rw quick
459
279 rw backing quick
460
280 rw migration quick
116
--
461
--
117
1.8.3.1
462
2.25.3
118
463
119
464
diff view generated by jsdifflib
1
In order to able to convert bdrv_truncate() to take a BdrvChild and
1
The BDRV_REQ_ZERO_WRITE is currently implemented in a way that first the
2
later to correctly check the resize permission here, we need to use a
2
image is possibly preallocated and then the zero flag is added to all
3
BlockBackend for resizing the image.
3
clusters. This means that a copy-on-write operation may be needed when
4
writing to these clusters, despite having used preallocation, negating
5
one of the major benefits of preallocation.
6
7
Instead, try to forward the BDRV_REQ_ZERO_WRITE to the protocol driver,
8
and if the protocol driver can ensure that the new area reads as zeros,
9
we can skip setting the zero flag in the qcow2 layer.
10
11
Unfortunately, the same approach doesn't work for metadata
12
preallocation, so we'll still set the zero flag there.
4
13
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
Reviewed-by: Max Reitz <mreitz@redhat.com>
15
Reviewed-by: Max Reitz <mreitz@redhat.com>
16
Message-Id: <20200424142701.67053-1-kwolf@redhat.com>
17
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
18
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
---
19
---
8
block/qcow2.c | 6 +++++-
20
block/qcow2.c | 22 +++++++++++++++++++---
9
1 file changed, 5 insertions(+), 1 deletion(-)
21
tests/qemu-iotests/274.out | 4 ++--
22
2 files changed, 21 insertions(+), 5 deletions(-)
10
23
11
diff --git a/block/qcow2.c b/block/qcow2.c
24
diff --git a/block/qcow2.c b/block/qcow2.c
12
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
13
--- a/block/qcow2.c
26
--- a/block/qcow2.c
14
+++ b/block/qcow2.c
27
+++ b/block/qcow2.c
15
@@ -XXX,XX +XXX,XX @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts,
28
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
16
}
29
/* Allocate the data area */
17
30
new_file_size = allocation_start +
18
if (new_size) {
31
nb_new_data_clusters * s->cluster_size;
19
- ret = bdrv_truncate(bs, new_size);
32
- /* Image file grows, so @exact does not matter */
20
+ BlockBackend *blk = blk_new();
33
- ret = bdrv_co_truncate(bs->file, new_file_size, false, prealloc, 0,
21
+ blk_insert_bs(blk, bs);
34
- errp);
22
+ ret = blk_truncate(blk, new_size);
35
+ /*
23
+ blk_unref(blk);
36
+ * Image file grows, so @exact does not matter.
24
+
37
+ *
38
+ * If we need to zero out the new area, try first whether the protocol
39
+ * driver can already take care of this.
40
+ */
41
+ if (flags & BDRV_REQ_ZERO_WRITE) {
42
+ ret = bdrv_co_truncate(bs->file, new_file_size, false, prealloc,
43
+ BDRV_REQ_ZERO_WRITE, NULL);
44
+ if (ret >= 0) {
45
+ flags &= ~BDRV_REQ_ZERO_WRITE;
46
+ }
47
+ } else {
48
+ ret = -1;
49
+ }
50
+ if (ret < 0) {
51
+ ret = bdrv_co_truncate(bs->file, new_file_size, false, prealloc, 0,
52
+ errp);
53
+ }
25
if (ret < 0) {
54
if (ret < 0) {
26
return ret;
55
error_prepend(errp, "Failed to resize underlying file: ");
27
}
56
qcow2_free_clusters(bs, allocation_start,
57
diff --git a/tests/qemu-iotests/274.out b/tests/qemu-iotests/274.out
58
index XXXXXXX..XXXXXXX 100644
59
--- a/tests/qemu-iotests/274.out
60
+++ b/tests/qemu-iotests/274.out
61
@@ -XXX,XX +XXX,XX @@ read 65536/65536 bytes at offset 9437184
62
10 MiB (0xa00000) bytes allocated at offset 5 MiB (0x500000)
63
64
[{ "start": 0, "length": 5242880, "depth": 1, "zero": true, "data": false},
65
-{ "start": 5242880, "length": 10485760, "depth": 0, "zero": true, "data": false, "offset": 327680}]
66
+{ "start": 5242880, "length": 10485760, "depth": 0, "zero": false, "data": true, "offset": 327680}]
67
68
=== preallocation=full ===
69
Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=16777216 cluster_size=65536 lazy_refcounts=off refcount_bits=16
70
@@ -XXX,XX +XXX,XX @@ read 65536/65536 bytes at offset 11534336
71
4 MiB (0x400000) bytes allocated at offset 8 MiB (0x800000)
72
73
[{ "start": 0, "length": 8388608, "depth": 1, "zero": true, "data": false},
74
-{ "start": 8388608, "length": 4194304, "depth": 0, "zero": true, "data": false, "offset": 327680}]
75
+{ "start": 8388608, "length": 4194304, "depth": 0, "zero": false, "data": true, "offset": 327680}]
76
77
=== preallocation=off ===
78
Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=393216 cluster_size=65536 lazy_refcounts=off refcount_bits=16
28
--
79
--
29
1.8.3.1
80
2.25.3
30
81
31
82
diff view generated by jsdifflib
1
From: Nir Soffer <nirsof@gmail.com>
1
From: Andrzej Jakowski <andrzej.jakowski@linux.intel.com>
2
2
3
When using file system that does not support fallocate() (e.g. NFS <
3
This patch introduces support for PMR that has been defined as part of NVMe 1.4
4
4.2), truncating the file only when preallocation=OFF speeds up creating
4
spec. User can now specify a pmrdev option that should point to HostMemoryBackend.
5
raw file.
5
pmrdev memory region will subsequently be exposed as PCI BAR 2 in emulated NVMe
6
device. Guest OS can perform mmio read and writes to the PMR region that will stay
7
persistent across system reboot.
6
8
7
Here is example run, tested on Fedora 24 machine, creating raw file on
9
Signed-off-by: Andrzej Jakowski <andrzej.jakowski@linux.intel.com>
8
NFS version 3 server.
10
Reviewed-by: Klaus Jensen <k.jensen@samsung.com>
9
11
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
10
$ time ./qemu-img-master create -f raw -o preallocation=falloc mnt/test 1g
12
Message-Id: <20200330164656.9348-1-andrzej.jakowski@linux.intel.com>
11
Formatting 'mnt/test', fmt=raw size=1073741824 preallocation=falloc
13
Reviewed-by: Keith Busch <kbusch@kernel.org>
12
13
real    0m21.185s
14
user    0m0.022s
15
sys    0m0.574s
16
17
$ time ./qemu-img-fix create -f raw -o preallocation=falloc mnt/test 1g
18
Formatting 'mnt/test', fmt=raw size=1073741824 preallocation=falloc
19
20
real    0m11.601s
21
user    0m0.016s
22
sys    0m0.525s
23
24
$ time dd if=/dev/zero of=mnt/test bs=1M count=1024 oflag=direct
25
1024+0 records in
26
1024+0 records out
27
1073741824 bytes (1.1 GB, 1.0 GiB) copied, 15.6627 s, 68.6 MB/s
28
29
real    0m16.104s
30
user    0m0.009s
31
sys    0m0.220s
32
33
Running with strace we can see that without this change we do one
34
pread() and one pwrite() for each block. With this change, we do only
35
one pwrite() per block.
36
37
$ strace ./qemu-img-master create -f raw -o preallocation=falloc mnt/test 8192
38
...
39
pread64(9, "\0", 1, 4095) = 1
40
pwrite64(9, "\0", 1, 4095) = 1
41
pread64(9, "\0", 1, 8191) = 1
42
pwrite64(9, "\0", 1, 8191) = 1
43
44
$ strace ./qemu-img-fix create -f raw -o preallocation=falloc mnt/test 8192
45
...
46
pwrite64(9, "\0", 1, 4095) = 1
47
pwrite64(9, "\0", 1, 8191) = 1
48
49
This happens because posix_fallocate is checking if each block is
50
allocated before writing a byte to the block, and when truncating the
51
file before preallocation, all blocks are unallocated.
52
53
Signed-off-by: Nir Soffer <nirsof@gmail.com>
54
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
55
---
15
---
56
block/file-posix.c | 11 ++++-------
16
hw/block/nvme.h | 2 +
57
1 file changed, 4 insertions(+), 7 deletions(-)
17
include/block/nvme.h | 172 +++++++++++++++++++++++++++++++++++++++++
18
hw/block/nvme.c | 109 ++++++++++++++++++++++++++
19
hw/block/Makefile.objs | 2 +-
20
hw/block/trace-events | 4 +
21
5 files changed, 288 insertions(+), 1 deletion(-)
58
22
59
diff --git a/block/file-posix.c b/block/file-posix.c
23
diff --git a/hw/block/nvme.h b/hw/block/nvme.h
60
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
61
--- a/block/file-posix.c
25
--- a/hw/block/nvme.h
62
+++ b/block/file-posix.c
26
+++ b/hw/block/nvme.h
63
@@ -XXX,XX +XXX,XX @@ static int raw_create(const char *filename, QemuOpts *opts, Error **errp)
27
@@ -XXX,XX +XXX,XX @@ typedef struct NvmeCtrl {
64
#endif
28
uint64_t timestamp_set_qemu_clock_ms; /* QEMU clock time */
29
30
char *serial;
31
+ HostMemoryBackend *pmrdev;
32
+
33
NvmeNamespace *namespaces;
34
NvmeSQueue **sq;
35
NvmeCQueue **cq;
36
diff --git a/include/block/nvme.h b/include/block/nvme.h
37
index XXXXXXX..XXXXXXX 100644
38
--- a/include/block/nvme.h
39
+++ b/include/block/nvme.h
40
@@ -XXX,XX +XXX,XX @@ typedef struct NvmeBar {
41
uint64_t acq;
42
uint32_t cmbloc;
43
uint32_t cmbsz;
44
+ uint8_t padding[3520]; /* not used by QEMU */
45
+ uint32_t pmrcap;
46
+ uint32_t pmrctl;
47
+ uint32_t pmrsts;
48
+ uint32_t pmrebs;
49
+ uint32_t pmrswtp;
50
+ uint32_t pmrmsc;
51
} NvmeBar;
52
53
enum NvmeCapShift {
54
@@ -XXX,XX +XXX,XX @@ enum NvmeCapShift {
55
CAP_CSS_SHIFT = 37,
56
CAP_MPSMIN_SHIFT = 48,
57
CAP_MPSMAX_SHIFT = 52,
58
+ CAP_PMR_SHIFT = 56,
59
};
60
61
enum NvmeCapMask {
62
@@ -XXX,XX +XXX,XX @@ enum NvmeCapMask {
63
CAP_CSS_MASK = 0xff,
64
CAP_MPSMIN_MASK = 0xf,
65
CAP_MPSMAX_MASK = 0xf,
66
+ CAP_PMR_MASK = 0x1,
67
};
68
69
#define NVME_CAP_MQES(cap) (((cap) >> CAP_MQES_SHIFT) & CAP_MQES_MASK)
70
@@ -XXX,XX +XXX,XX @@ enum NvmeCapMask {
71
<< CAP_MPSMIN_SHIFT)
72
#define NVME_CAP_SET_MPSMAX(cap, val) (cap |= (uint64_t)(val & CAP_MPSMAX_MASK)\
73
<< CAP_MPSMAX_SHIFT)
74
+#define NVME_CAP_SET_PMRS(cap, val) (cap |= (uint64_t)(val & CAP_PMR_MASK)\
75
+ << CAP_PMR_SHIFT)
76
77
enum NvmeCcShift {
78
CC_EN_SHIFT = 0,
79
@@ -XXX,XX +XXX,XX @@ enum NvmeCmbszMask {
80
#define NVME_CMBSZ_GETSIZE(cmbsz) \
81
(NVME_CMBSZ_SZ(cmbsz) * (1 << (12 + 4 * NVME_CMBSZ_SZU(cmbsz))))
82
83
+enum NvmePmrcapShift {
84
+ PMRCAP_RDS_SHIFT = 3,
85
+ PMRCAP_WDS_SHIFT = 4,
86
+ PMRCAP_BIR_SHIFT = 5,
87
+ PMRCAP_PMRTU_SHIFT = 8,
88
+ PMRCAP_PMRWBM_SHIFT = 10,
89
+ PMRCAP_PMRTO_SHIFT = 16,
90
+ PMRCAP_CMSS_SHIFT = 24,
91
+};
92
+
93
+enum NvmePmrcapMask {
94
+ PMRCAP_RDS_MASK = 0x1,
95
+ PMRCAP_WDS_MASK = 0x1,
96
+ PMRCAP_BIR_MASK = 0x7,
97
+ PMRCAP_PMRTU_MASK = 0x3,
98
+ PMRCAP_PMRWBM_MASK = 0xf,
99
+ PMRCAP_PMRTO_MASK = 0xff,
100
+ PMRCAP_CMSS_MASK = 0x1,
101
+};
102
+
103
+#define NVME_PMRCAP_RDS(pmrcap) \
104
+ ((pmrcap >> PMRCAP_RDS_SHIFT) & PMRCAP_RDS_MASK)
105
+#define NVME_PMRCAP_WDS(pmrcap) \
106
+ ((pmrcap >> PMRCAP_WDS_SHIFT) & PMRCAP_WDS_MASK)
107
+#define NVME_PMRCAP_BIR(pmrcap) \
108
+ ((pmrcap >> PMRCAP_BIR_SHIFT) & PMRCAP_BIR_MASK)
109
+#define NVME_PMRCAP_PMRTU(pmrcap) \
110
+ ((pmrcap >> PMRCAP_PMRTU_SHIFT) & PMRCAP_PMRTU_MASK)
111
+#define NVME_PMRCAP_PMRWBM(pmrcap) \
112
+ ((pmrcap >> PMRCAP_PMRWBM_SHIFT) & PMRCAP_PMRWBM_MASK)
113
+#define NVME_PMRCAP_PMRTO(pmrcap) \
114
+ ((pmrcap >> PMRCAP_PMRTO_SHIFT) & PMRCAP_PMRTO_MASK)
115
+#define NVME_PMRCAP_CMSS(pmrcap) \
116
+ ((pmrcap >> PMRCAP_CMSS_SHIFT) & PMRCAP_CMSS_MASK)
117
+
118
+#define NVME_PMRCAP_SET_RDS(pmrcap, val) \
119
+ (pmrcap |= (uint64_t)(val & PMRCAP_RDS_MASK) << PMRCAP_RDS_SHIFT)
120
+#define NVME_PMRCAP_SET_WDS(pmrcap, val) \
121
+ (pmrcap |= (uint64_t)(val & PMRCAP_WDS_MASK) << PMRCAP_WDS_SHIFT)
122
+#define NVME_PMRCAP_SET_BIR(pmrcap, val) \
123
+ (pmrcap |= (uint64_t)(val & PMRCAP_BIR_MASK) << PMRCAP_BIR_SHIFT)
124
+#define NVME_PMRCAP_SET_PMRTU(pmrcap, val) \
125
+ (pmrcap |= (uint64_t)(val & PMRCAP_PMRTU_MASK) << PMRCAP_PMRTU_SHIFT)
126
+#define NVME_PMRCAP_SET_PMRWBM(pmrcap, val) \
127
+ (pmrcap |= (uint64_t)(val & PMRCAP_PMRWBM_MASK) << PMRCAP_PMRWBM_SHIFT)
128
+#define NVME_PMRCAP_SET_PMRTO(pmrcap, val) \
129
+ (pmrcap |= (uint64_t)(val & PMRCAP_PMRTO_MASK) << PMRCAP_PMRTO_SHIFT)
130
+#define NVME_PMRCAP_SET_CMSS(pmrcap, val) \
131
+ (pmrcap |= (uint64_t)(val & PMRCAP_CMSS_MASK) << PMRCAP_CMSS_SHIFT)
132
+
133
+enum NvmePmrctlShift {
134
+ PMRCTL_EN_SHIFT = 0,
135
+};
136
+
137
+enum NvmePmrctlMask {
138
+ PMRCTL_EN_MASK = 0x1,
139
+};
140
+
141
+#define NVME_PMRCTL_EN(pmrctl) ((pmrctl >> PMRCTL_EN_SHIFT) & PMRCTL_EN_MASK)
142
+
143
+#define NVME_PMRCTL_SET_EN(pmrctl, val) \
144
+ (pmrctl |= (uint64_t)(val & PMRCTL_EN_MASK) << PMRCTL_EN_SHIFT)
145
+
146
+enum NvmePmrstsShift {
147
+ PMRSTS_ERR_SHIFT = 0,
148
+ PMRSTS_NRDY_SHIFT = 8,
149
+ PMRSTS_HSTS_SHIFT = 9,
150
+ PMRSTS_CBAI_SHIFT = 12,
151
+};
152
+
153
+enum NvmePmrstsMask {
154
+ PMRSTS_ERR_MASK = 0xff,
155
+ PMRSTS_NRDY_MASK = 0x1,
156
+ PMRSTS_HSTS_MASK = 0x7,
157
+ PMRSTS_CBAI_MASK = 0x1,
158
+};
159
+
160
+#define NVME_PMRSTS_ERR(pmrsts) \
161
+ ((pmrsts >> PMRSTS_ERR_SHIFT) & PMRSTS_ERR_MASK)
162
+#define NVME_PMRSTS_NRDY(pmrsts) \
163
+ ((pmrsts >> PMRSTS_NRDY_SHIFT) & PMRSTS_NRDY_MASK)
164
+#define NVME_PMRSTS_HSTS(pmrsts) \
165
+ ((pmrsts >> PMRSTS_HSTS_SHIFT) & PMRSTS_HSTS_MASK)
166
+#define NVME_PMRSTS_CBAI(pmrsts) \
167
+ ((pmrsts >> PMRSTS_CBAI_SHIFT) & PMRSTS_CBAI_MASK)
168
+
169
+#define NVME_PMRSTS_SET_ERR(pmrsts, val) \
170
+ (pmrsts |= (uint64_t)(val & PMRSTS_ERR_MASK) << PMRSTS_ERR_SHIFT)
171
+#define NVME_PMRSTS_SET_NRDY(pmrsts, val) \
172
+ (pmrsts |= (uint64_t)(val & PMRSTS_NRDY_MASK) << PMRSTS_NRDY_SHIFT)
173
+#define NVME_PMRSTS_SET_HSTS(pmrsts, val) \
174
+ (pmrsts |= (uint64_t)(val & PMRSTS_HSTS_MASK) << PMRSTS_HSTS_SHIFT)
175
+#define NVME_PMRSTS_SET_CBAI(pmrsts, val) \
176
+ (pmrsts |= (uint64_t)(val & PMRSTS_CBAI_MASK) << PMRSTS_CBAI_SHIFT)
177
+
178
+enum NvmePmrebsShift {
179
+ PMREBS_PMRSZU_SHIFT = 0,
180
+ PMREBS_RBB_SHIFT = 4,
181
+ PMREBS_PMRWBZ_SHIFT = 8,
182
+};
183
+
184
+enum NvmePmrebsMask {
185
+ PMREBS_PMRSZU_MASK = 0xf,
186
+ PMREBS_RBB_MASK = 0x1,
187
+ PMREBS_PMRWBZ_MASK = 0xffffff,
188
+};
189
+
190
+#define NVME_PMREBS_PMRSZU(pmrebs) \
191
+ ((pmrebs >> PMREBS_PMRSZU_SHIFT) & PMREBS_PMRSZU_MASK)
192
+#define NVME_PMREBS_RBB(pmrebs) \
193
+ ((pmrebs >> PMREBS_RBB_SHIFT) & PMREBS_RBB_MASK)
194
+#define NVME_PMREBS_PMRWBZ(pmrebs) \
195
+ ((pmrebs >> PMREBS_PMRWBZ_SHIFT) & PMREBS_PMRWBZ_MASK)
196
+
197
+#define NVME_PMREBS_SET_PMRSZU(pmrebs, val) \
198
+ (pmrebs |= (uint64_t)(val & PMREBS_PMRSZU_MASK) << PMREBS_PMRSZU_SHIFT)
199
+#define NVME_PMREBS_SET_RBB(pmrebs, val) \
200
+ (pmrebs |= (uint64_t)(val & PMREBS_RBB_MASK) << PMREBS_RBB_SHIFT)
201
+#define NVME_PMREBS_SET_PMRWBZ(pmrebs, val) \
202
+ (pmrebs |= (uint64_t)(val & PMREBS_PMRWBZ_MASK) << PMREBS_PMRWBZ_SHIFT)
203
+
204
+enum NvmePmrswtpShift {
205
+ PMRSWTP_PMRSWTU_SHIFT = 0,
206
+ PMRSWTP_PMRSWTV_SHIFT = 8,
207
+};
208
+
209
+enum NvmePmrswtpMask {
210
+ PMRSWTP_PMRSWTU_MASK = 0xf,
211
+ PMRSWTP_PMRSWTV_MASK = 0xffffff,
212
+};
213
+
214
+#define NVME_PMRSWTP_PMRSWTU(pmrswtp) \
215
+ ((pmrswtp >> PMRSWTP_PMRSWTU_SHIFT) & PMRSWTP_PMRSWTU_MASK)
216
+#define NVME_PMRSWTP_PMRSWTV(pmrswtp) \
217
+ ((pmrswtp >> PMRSWTP_PMRSWTV_SHIFT) & PMRSWTP_PMRSWTV_MASK)
218
+
219
+#define NVME_PMRSWTP_SET_PMRSWTU(pmrswtp, val) \
220
+ (pmrswtp |= (uint64_t)(val & PMRSWTP_PMRSWTU_MASK) << PMRSWTP_PMRSWTU_SHIFT)
221
+#define NVME_PMRSWTP_SET_PMRSWTV(pmrswtp, val) \
222
+ (pmrswtp |= (uint64_t)(val & PMRSWTP_PMRSWTV_MASK) << PMRSWTP_PMRSWTV_SHIFT)
223
+
224
+enum NvmePmrmscShift {
225
+ PMRMSC_CMSE_SHIFT = 1,
226
+ PMRMSC_CBA_SHIFT = 12,
227
+};
228
+
229
+enum NvmePmrmscMask {
230
+ PMRMSC_CMSE_MASK = 0x1,
231
+ PMRMSC_CBA_MASK = 0xfffffffffffff,
232
+};
233
+
234
+#define NVME_PMRMSC_CMSE(pmrmsc) \
235
+ ((pmrmsc >> PMRMSC_CMSE_SHIFT) & PMRMSC_CMSE_MASK)
236
+#define NVME_PMRMSC_CBA(pmrmsc) \
237
+ ((pmrmsc >> PMRMSC_CBA_SHIFT) & PMRMSC_CBA_MASK)
238
+
239
+#define NVME_PMRMSC_SET_CMSE(pmrmsc, val) \
240
+ (pmrmsc |= (uint64_t)(val & PMRMSC_CMSE_MASK) << PMRMSC_CMSE_SHIFT)
241
+#define NVME_PMRMSC_SET_CBA(pmrmsc, val) \
242
+ (pmrmsc |= (uint64_t)(val & PMRMSC_CBA_MASK) << PMRMSC_CBA_SHIFT)
243
+
244
typedef struct NvmeCmd {
245
uint8_t opcode;
246
uint8_t fuse;
247
diff --git a/hw/block/nvme.c b/hw/block/nvme.c
248
index XXXXXXX..XXXXXXX 100644
249
--- a/hw/block/nvme.c
250
+++ b/hw/block/nvme.c
251
@@ -XXX,XX +XXX,XX @@
252
* -drive file=<file>,if=none,id=<drive_id>
253
* -device nvme,drive=<drive_id>,serial=<serial>,id=<id[optional]>, \
254
* cmb_size_mb=<cmb_size_mb[optional]>, \
255
+ * [pmrdev=<mem_backend_file_id>,] \
256
* num_queues=<N[optional]>
257
*
258
* Note cmb_size_mb denotes size of CMB in MB. CMB is assumed to be at
259
* offset 0 in BAR2 and supports only WDS, RDS and SQS for now.
260
+ *
261
+ * cmb_size_mb= and pmrdev= options are mutually exclusive due to limitation
262
+ * in available BAR's. cmb_size_mb= will take precedence over pmrdev= when
263
+ * both provided.
264
+ * Enabling pmr emulation can be achieved by pointing to memory-backend-file.
265
+ * For example:
266
+ * -object memory-backend-file,id=<mem_id>,share=on,mem-path=<file_path>, \
267
+ * size=<size> .... -device nvme,...,pmrdev=<mem_id>
268
*/
269
270
#include "qemu/osdep.h"
271
@@ -XXX,XX +XXX,XX @@
272
#include "sysemu/sysemu.h"
273
#include "qapi/error.h"
274
#include "qapi/visitor.h"
275
+#include "sysemu/hostmem.h"
276
#include "sysemu/block-backend.h"
277
+#include "exec/ram_addr.h"
278
279
#include "qemu/log.h"
280
#include "qemu/module.h"
281
@@ -XXX,XX +XXX,XX @@ static void nvme_write_bar(NvmeCtrl *n, hwaddr offset, uint64_t data,
282
NVME_GUEST_ERR(nvme_ub_mmiowr_cmbsz_readonly,
283
"invalid write to read only CMBSZ, ignored");
284
return;
285
+ case 0xE00: /* PMRCAP */
286
+ NVME_GUEST_ERR(nvme_ub_mmiowr_pmrcap_readonly,
287
+ "invalid write to PMRCAP register, ignored");
288
+ return;
289
+ case 0xE04: /* TODO PMRCTL */
290
+ break;
291
+ case 0xE08: /* PMRSTS */
292
+ NVME_GUEST_ERR(nvme_ub_mmiowr_pmrsts_readonly,
293
+ "invalid write to PMRSTS register, ignored");
294
+ return;
295
+ case 0xE0C: /* PMREBS */
296
+ NVME_GUEST_ERR(nvme_ub_mmiowr_pmrebs_readonly,
297
+ "invalid write to PMREBS register, ignored");
298
+ return;
299
+ case 0xE10: /* PMRSWTP */
300
+ NVME_GUEST_ERR(nvme_ub_mmiowr_pmrswtp_readonly,
301
+ "invalid write to PMRSWTP register, ignored");
302
+ return;
303
+ case 0xE14: /* TODO PMRMSC */
304
+ break;
305
default:
306
NVME_GUEST_ERR(nvme_ub_mmiowr_invalid,
307
"invalid MMIO write,"
308
@@ -XXX,XX +XXX,XX @@ static uint64_t nvme_mmio_read(void *opaque, hwaddr addr, unsigned size)
65
}
309
}
66
310
67
- if (ftruncate(fd, total_size) != 0) {
311
if (addr < sizeof(n->bar)) {
68
- result = -errno;
312
+ /*
69
- error_setg_errno(errp, -result, "Could not resize file");
313
+ * When PMRWBM bit 1 is set then read from
70
- goto out_close;
314
+ * from PMRSTS should ensure prior writes
71
- }
315
+ * made it to persistent media
72
-
316
+ */
73
switch (prealloc) {
317
+ if (addr == 0xE08 &&
74
#ifdef CONFIG_POSIX_FALLOCATE
318
+ (NVME_PMRCAP_PMRWBM(n->bar.pmrcap) & 0x02)) {
75
case PREALLOC_MODE_FALLOC:
319
+ qemu_ram_writeback(n->pmrdev->mr.ram_block,
76
@@ -XXX,XX +XXX,XX @@ static int raw_create(const char *filename, QemuOpts *opts, Error **errp)
320
+ 0, n->pmrdev->size);
77
break;
321
+ }
322
memcpy(&val, ptr + addr, size);
323
} else {
324
NVME_GUEST_ERR(nvme_ub_mmiord_invalid_ofs,
325
@@ -XXX,XX +XXX,XX @@ static void nvme_realize(PCIDevice *pci_dev, Error **errp)
326
error_setg(errp, "serial property not set");
327
return;
78
}
328
}
79
case PREALLOC_MODE_OFF:
329
+
80
+ if (ftruncate(fd, total_size) != 0) {
330
+ if (!n->cmb_size_mb && n->pmrdev) {
81
+ result = -errno;
331
+ if (host_memory_backend_is_mapped(n->pmrdev)) {
82
+ error_setg_errno(errp, -result, "Could not resize file");
332
+ char *path = object_get_canonical_path_component(OBJECT(n->pmrdev));
333
+ error_setg(errp, "can't use already busy memdev: %s", path);
334
+ g_free(path);
335
+ return;
83
+ }
336
+ }
84
break;
337
+
85
default:
338
+ if (!is_power_of_2(n->pmrdev->size)) {
86
result = -EINVAL;
339
+ error_setg(errp, "pmr backend size needs to be power of 2 in size");
87
@@ -XXX,XX +XXX,XX @@ static int raw_create(const char *filename, QemuOpts *opts, Error **errp)
340
+ return;
88
break;
341
+ }
342
+
343
+ host_memory_backend_set_mapped(n->pmrdev, true);
344
+ }
345
+
346
blkconf_blocksizes(&n->conf);
347
if (!blkconf_apply_backend_options(&n->conf, blk_is_read_only(n->conf.blk),
348
false, errp)) {
349
@@ -XXX,XX +XXX,XX @@ static void nvme_realize(PCIDevice *pci_dev, Error **errp)
350
PCI_BASE_ADDRESS_SPACE_MEMORY | PCI_BASE_ADDRESS_MEM_TYPE_64 |
351
PCI_BASE_ADDRESS_MEM_PREFETCH, &n->ctrl_mem);
352
353
+ } else if (n->pmrdev) {
354
+ /* Controller Capabilities register */
355
+ NVME_CAP_SET_PMRS(n->bar.cap, 1);
356
+
357
+ /* PMR Capabities register */
358
+ n->bar.pmrcap = 0;
359
+ NVME_PMRCAP_SET_RDS(n->bar.pmrcap, 0);
360
+ NVME_PMRCAP_SET_WDS(n->bar.pmrcap, 0);
361
+ NVME_PMRCAP_SET_BIR(n->bar.pmrcap, 2);
362
+ NVME_PMRCAP_SET_PMRTU(n->bar.pmrcap, 0);
363
+ /* Turn on bit 1 support */
364
+ NVME_PMRCAP_SET_PMRWBM(n->bar.pmrcap, 0x02);
365
+ NVME_PMRCAP_SET_PMRTO(n->bar.pmrcap, 0);
366
+ NVME_PMRCAP_SET_CMSS(n->bar.pmrcap, 0);
367
+
368
+ /* PMR Control register */
369
+ n->bar.pmrctl = 0;
370
+ NVME_PMRCTL_SET_EN(n->bar.pmrctl, 0);
371
+
372
+ /* PMR Status register */
373
+ n->bar.pmrsts = 0;
374
+ NVME_PMRSTS_SET_ERR(n->bar.pmrsts, 0);
375
+ NVME_PMRSTS_SET_NRDY(n->bar.pmrsts, 0);
376
+ NVME_PMRSTS_SET_HSTS(n->bar.pmrsts, 0);
377
+ NVME_PMRSTS_SET_CBAI(n->bar.pmrsts, 0);
378
+
379
+ /* PMR Elasticity Buffer Size register */
380
+ n->bar.pmrebs = 0;
381
+ NVME_PMREBS_SET_PMRSZU(n->bar.pmrebs, 0);
382
+ NVME_PMREBS_SET_RBB(n->bar.pmrebs, 0);
383
+ NVME_PMREBS_SET_PMRWBZ(n->bar.pmrebs, 0);
384
+
385
+ /* PMR Sustained Write Throughput register */
386
+ n->bar.pmrswtp = 0;
387
+ NVME_PMRSWTP_SET_PMRSWTU(n->bar.pmrswtp, 0);
388
+ NVME_PMRSWTP_SET_PMRSWTV(n->bar.pmrswtp, 0);
389
+
390
+ /* PMR Memory Space Control register */
391
+ n->bar.pmrmsc = 0;
392
+ NVME_PMRMSC_SET_CMSE(n->bar.pmrmsc, 0);
393
+ NVME_PMRMSC_SET_CBA(n->bar.pmrmsc, 0);
394
+
395
+ pci_register_bar(pci_dev, NVME_PMRCAP_BIR(n->bar.pmrcap),
396
+ PCI_BASE_ADDRESS_SPACE_MEMORY | PCI_BASE_ADDRESS_MEM_TYPE_64 |
397
+ PCI_BASE_ADDRESS_MEM_PREFETCH, &n->pmrdev->mr);
89
}
398
}
90
399
91
-out_close:
400
for (i = 0; i < n->num_namespaces; i++) {
92
if (qemu_close(fd) != 0 && result == 0) {
401
@@ -XXX,XX +XXX,XX @@ static void nvme_exit(PCIDevice *pci_dev)
93
result = -errno;
402
if (n->cmb_size_mb) {
94
error_setg_errno(errp, -result, "Could not close the new file");
403
g_free(n->cmbuf);
404
}
405
+
406
+ if (n->pmrdev) {
407
+ host_memory_backend_set_mapped(n->pmrdev, false);
408
+ }
409
msix_uninit_exclusive_bar(pci_dev);
410
}
411
412
static Property nvme_props[] = {
413
DEFINE_BLOCK_PROPERTIES(NvmeCtrl, conf),
414
+ DEFINE_PROP_LINK("pmrdev", NvmeCtrl, pmrdev, TYPE_MEMORY_BACKEND,
415
+ HostMemoryBackend *),
416
DEFINE_PROP_STRING("serial", NvmeCtrl, serial),
417
DEFINE_PROP_UINT32("cmb_size_mb", NvmeCtrl, cmb_size_mb, 0),
418
DEFINE_PROP_UINT32("num_queues", NvmeCtrl, num_queues, 64),
419
diff --git a/hw/block/Makefile.objs b/hw/block/Makefile.objs
420
index XXXXXXX..XXXXXXX 100644
421
--- a/hw/block/Makefile.objs
422
+++ b/hw/block/Makefile.objs
423
@@ -XXX,XX +XXX,XX @@ common-obj-$(CONFIG_PFLASH_CFI02) += pflash_cfi02.o
424
common-obj-$(CONFIG_XEN) += xen-block.o
425
common-obj-$(CONFIG_ECC) += ecc.o
426
common-obj-$(CONFIG_ONENAND) += onenand.o
427
-common-obj-$(CONFIG_NVME_PCI) += nvme.o
428
common-obj-$(CONFIG_SWIM) += swim.o
429
430
common-obj-$(CONFIG_SH4) += tc58128.o
431
432
obj-$(CONFIG_VIRTIO_BLK) += virtio-blk.o
433
obj-$(CONFIG_VHOST_USER_BLK) += vhost-user-blk.o
434
+obj-$(CONFIG_NVME_PCI) += nvme.o
435
436
obj-y += dataplane/
437
diff --git a/hw/block/trace-events b/hw/block/trace-events
438
index XXXXXXX..XXXXXXX 100644
439
--- a/hw/block/trace-events
440
+++ b/hw/block/trace-events
441
@@ -XXX,XX +XXX,XX @@ nvme_ub_mmiowr_ssreset_w1c_unsupported(void) "attempted to W1C CSTS.NSSRO but CA
442
nvme_ub_mmiowr_ssreset_unsupported(void) "attempted NVM subsystem reset but CAP.NSSRS is zero (not supported)"
443
nvme_ub_mmiowr_cmbloc_reserved(void) "invalid write to reserved CMBLOC when CMBSZ is zero, ignored"
444
nvme_ub_mmiowr_cmbsz_readonly(void) "invalid write to read only CMBSZ, ignored"
445
+nvme_ub_mmiowr_pmrcap_readonly(void) "invalid write to read only PMRCAP, ignored"
446
+nvme_ub_mmiowr_pmrsts_readonly(void) "invalid write to read only PMRSTS, ignored"
447
+nvme_ub_mmiowr_pmrebs_readonly(void) "invalid write to read only PMREBS, ignored"
448
+nvme_ub_mmiowr_pmrswtp_readonly(void) "invalid write to read only PMRSWTP, ignored"
449
nvme_ub_mmiowr_invalid(uint64_t offset, uint64_t data) "invalid MMIO write, offset=0x%"PRIx64", data=0x%"PRIx64""
450
nvme_ub_mmiord_misaligned32(uint64_t offset) "MMIO read not 32-bit aligned, offset=0x%"PRIx64""
451
nvme_ub_mmiord_toosmall(uint64_t offset) "MMIO read smaller than 32-bits, offset=0x%"PRIx64""
95
--
452
--
96
1.8.3.1
453
2.25.3
97
454
98
455
diff view generated by jsdifflib
1
This is the part of bdrv_open_child() that opens a BDS with option
1
The QMP handler qmp_object_add() and the implementation of --object in
2
inheritance, but doesn't attach it as a child to the parent yet.
2
qemu-storage-daemon can share most of the code. Currently,
3
qemu-storage-daemon calls qmp_object_add(), but this is not correct
4
because different visitors need to be used.
5
6
As a first step towards a fix, make qmp_object_add() a wrapper around a
7
new function user_creatable_add_dict() that can get an additional
8
parameter. The handling of "props" is only required for compatibility
9
and not required for the qemu-storage-daemon command line, so it stays
10
in qmp_object_add().
3
11
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
Reviewed-by: Max Reitz <mreitz@redhat.com>
6
---
13
---
7
block.c | 61 +++++++++++++++++++++++++++++++++++++------------------------
14
include/qom/object_interfaces.h | 12 ++++++++++++
8
1 file changed, 37 insertions(+), 24 deletions(-)
15
qom/object_interfaces.c | 27 +++++++++++++++++++++++++++
16
qom/qom-qmp-cmds.c | 24 +-----------------------
17
3 files changed, 40 insertions(+), 23 deletions(-)
9
18
10
diff --git a/block.c b/block.c
19
diff --git a/include/qom/object_interfaces.h b/include/qom/object_interfaces.h
11
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
12
--- a/block.c
21
--- a/include/qom/object_interfaces.h
13
+++ b/block.c
22
+++ b/include/qom/object_interfaces.h
14
@@ -XXX,XX +XXX,XX @@ free_exit:
23
@@ -XXX,XX +XXX,XX @@ Object *user_creatable_add_type(const char *type, const char *id,
15
return ret;
24
const QDict *qdict,
25
Visitor *v, Error **errp);
26
27
+/**
28
+ * user_creatable_add_dict:
29
+ * @qdict: the object definition
30
+ * @errp: if an error occurs, a pointer to an area to store the error
31
+ *
32
+ * Create an instance of the user creatable object that is defined by
33
+ * @qdict. The object type is taken from the QDict key 'qom-type', its
34
+ * ID from the key 'id'. The remaining entries in @qdict are used to
35
+ * initialize the object properties.
36
+ */
37
+void user_creatable_add_dict(QDict *qdict, Error **errp);
38
+
39
/**
40
* user_creatable_add_opts:
41
* @opts: the object definition
42
diff --git a/qom/object_interfaces.c b/qom/object_interfaces.c
43
index XXXXXXX..XXXXXXX 100644
44
--- a/qom/object_interfaces.c
45
+++ b/qom/object_interfaces.c
46
@@ -XXX,XX +XXX,XX @@
47
#include "qapi/qmp/qerror.h"
48
#include "qapi/qmp/qjson.h"
49
#include "qapi/qmp/qstring.h"
50
+#include "qapi/qobject-input-visitor.h"
51
#include "qom/object_interfaces.h"
52
#include "qemu/help_option.h"
53
#include "qemu/module.h"
54
@@ -XXX,XX +XXX,XX @@ out:
55
return obj;
16
}
56
}
17
57
18
-/*
58
+void user_creatable_add_dict(QDict *qdict, Error **errp)
19
- * Opens a disk image whose options are given as BlockdevRef in another block
59
+{
20
- * device's options.
60
+ Visitor *v;
21
- *
61
+ Object *obj;
22
- * If allow_none is true, no image will be opened if filename is false and no
62
+ g_autofree char *type = NULL;
23
- * BlockdevRef is given. NULL will be returned, but errp remains unset.
63
+ g_autofree char *id = NULL;
24
- *
64
+
25
- * bdrev_key specifies the key for the image's BlockdevRef in the options QDict.
65
+ type = g_strdup(qdict_get_try_str(qdict, "qom-type"));
26
- * That QDict has to be flattened; therefore, if the BlockdevRef is a QDict
66
+ if (!type) {
27
- * itself, all options starting with "${bdref_key}." are considered part of the
67
+ error_setg(errp, QERR_MISSING_PARAMETER, "qom-type");
28
- * BlockdevRef.
68
+ return;
29
- *
69
+ }
30
- * The BlockdevRef will be removed from the options QDict.
70
+ qdict_del(qdict, "qom-type");
31
- */
71
+
32
-BdrvChild *bdrv_open_child(const char *filename,
72
+ id = g_strdup(qdict_get_try_str(qdict, "id"));
33
- QDict *options, const char *bdref_key,
73
+ if (!id) {
34
- BlockDriverState* parent,
74
+ error_setg(errp, QERR_MISSING_PARAMETER, "id");
35
- const BdrvChildRole *child_role,
75
+ return;
36
- bool allow_none, Error **errp)
76
+ }
37
+static BlockDriverState *
77
+ qdict_del(qdict, "id");
38
+bdrv_open_child_bs(const char *filename, QDict *options, const char *bdref_key,
78
+
39
+ BlockDriverState *parent, const BdrvChildRole *child_role,
79
+ v = qobject_input_visitor_new(QOBJECT(qdict));
40
+ bool allow_none, Error **errp)
80
+ obj = user_creatable_add_type(type, id, qdict, v, errp);
81
+ visit_free(v);
82
+ object_unref(obj);
83
+}
84
85
Object *user_creatable_add_opts(QemuOpts *opts, Error **errp)
41
{
86
{
42
- BdrvChild *c = NULL;
87
diff --git a/qom/qom-qmp-cmds.c b/qom/qom-qmp-cmds.c
43
- BlockDriverState *bs;
88
index XXXXXXX..XXXXXXX 100644
44
+ BlockDriverState *bs = NULL;
89
--- a/qom/qom-qmp-cmds.c
45
QDict *image_options;
90
+++ b/qom/qom-qmp-cmds.c
46
char *bdref_key_dot;
91
@@ -XXX,XX +XXX,XX @@
47
const char *reference;
92
#include "qapi/qapi-commands-qom.h"
48
@@ -XXX,XX +XXX,XX @@ BdrvChild *bdrv_open_child(const char *filename,
93
#include "qapi/qmp/qdict.h"
49
goto done;
94
#include "qapi/qmp/qerror.h"
95
-#include "qapi/qobject-input-visitor.h"
96
#include "qemu/cutils.h"
97
#include "qom/object_interfaces.h"
98
#include "qom/qom-qobject.h"
99
@@ -XXX,XX +XXX,XX @@ void qmp_object_add(QDict *qdict, QObject **ret_data, Error **errp)
100
{
101
QObject *props;
102
QDict *pdict;
103
- Visitor *v;
104
- Object *obj;
105
- g_autofree char *type = NULL;
106
- g_autofree char *id = NULL;
107
-
108
- type = g_strdup(qdict_get_try_str(qdict, "qom-type"));
109
- if (!type) {
110
- error_setg(errp, QERR_MISSING_PARAMETER, "qom-type");
111
- return;
112
- }
113
- qdict_del(qdict, "qom-type");
114
-
115
- id = g_strdup(qdict_get_try_str(qdict, "id"));
116
- if (!id) {
117
- error_setg(errp, QERR_MISSING_PARAMETER, "id");
118
- return;
119
- }
120
- qdict_del(qdict, "id");
121
122
props = qdict_get(qdict, "props");
123
if (props) {
124
@@ -XXX,XX +XXX,XX @@ void qmp_object_add(QDict *qdict, QObject **ret_data, Error **errp)
125
qobject_unref(pdict);
50
}
126
}
51
127
52
- c = bdrv_attach_child(parent, bs, bdref_key, child_role);
128
- v = qobject_input_visitor_new(QOBJECT(qdict));
53
-
129
- obj = user_creatable_add_type(type, id, qdict, v, errp);
54
done:
130
- visit_free(v);
55
qdict_del(options, bdref_key);
131
- object_unref(obj);
56
- return c;
132
+ user_creatable_add_dict(qdict, errp);
57
+ return bs;
58
+}
59
+
60
+/*
61
+ * Opens a disk image whose options are given as BlockdevRef in another block
62
+ * device's options.
63
+ *
64
+ * If allow_none is true, no image will be opened if filename is false and no
65
+ * BlockdevRef is given. NULL will be returned, but errp remains unset.
66
+ *
67
+ * bdrev_key specifies the key for the image's BlockdevRef in the options QDict.
68
+ * That QDict has to be flattened; therefore, if the BlockdevRef is a QDict
69
+ * itself, all options starting with "${bdref_key}." are considered part of the
70
+ * BlockdevRef.
71
+ *
72
+ * The BlockdevRef will be removed from the options QDict.
73
+ */
74
+BdrvChild *bdrv_open_child(const char *filename,
75
+ QDict *options, const char *bdref_key,
76
+ BlockDriverState *parent,
77
+ const BdrvChildRole *child_role,
78
+ bool allow_none, Error **errp)
79
+{
80
+ BlockDriverState *bs;
81
+
82
+ bs = bdrv_open_child_bs(filename, options, bdref_key, parent, child_role,
83
+ allow_none, errp);
84
+ if (bs == NULL) {
85
+ return NULL;
86
+ }
87
+
88
+ return bdrv_attach_child(parent, bs, bdref_key, child_role);
89
}
133
}
90
134
91
static BlockDriverState *bdrv_append_temp_snapshot(BlockDriverState *bs,
135
void qmp_object_del(const char *id, Error **errp)
92
--
136
--
93
1.8.3.1
137
2.25.3
94
138
95
139
diff view generated by jsdifflib
1
From: Jeff Cody <jcody@redhat.com>
1
After processing the option string with the keyval parser, we get a
2
QDict that contains only strings. This QDict must be fed to a keyval
3
visitor which converts the strings into the right data types.
2
4
3
Add the ability for shell script tests to exclude specific
5
qmp_object_add(), however, uses the normal QObject input visitor, which
4
protocols. This is useful to allow all protocols except ones known to
6
expects a QDict where all properties already have the QType that matches
5
not support a feature used in the test (e.g. .bdrv_create).
7
the data type required by the QOM object type.
6
8
7
Signed-off-by: Jeff Cody <jcody@redhat.com>
9
Change the --object implementation in qemu-storage-daemon so that it
10
doesn't call qmp_object_add(), but calls user_creatable_add_dict()
11
directly instead and pass it a new keyval boolean that decides which
12
visitor must be used.
13
14
Reported-by: Coiby Xu <coiby.xu@gmail.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
16
---
10
tests/qemu-iotests/common.rc | 12 ++++++++++++
17
include/qom/object_interfaces.h | 6 +++++-
11
1 file changed, 12 insertions(+)
18
qemu-storage-daemon.c | 4 +---
19
qom/object_interfaces.c | 8 ++++++--
20
qom/qom-qmp-cmds.c | 2 +-
21
4 files changed, 13 insertions(+), 7 deletions(-)
12
22
13
diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc
23
diff --git a/include/qom/object_interfaces.h b/include/qom/object_interfaces.h
14
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
15
--- a/tests/qemu-iotests/common.rc
25
--- a/include/qom/object_interfaces.h
16
+++ b/tests/qemu-iotests/common.rc
26
+++ b/include/qom/object_interfaces.h
17
@@ -XXX,XX +XXX,XX @@ _supported_proto()
27
@@ -XXX,XX +XXX,XX @@ Object *user_creatable_add_type(const char *type, const char *id,
18
_notrun "not suitable for this image protocol: $IMGPROTO"
28
/**
29
* user_creatable_add_dict:
30
* @qdict: the object definition
31
+ * @keyval: if true, use a keyval visitor for processing @qdict (i.e.
32
+ * assume that all @qdict values are strings); otherwise, use
33
+ * the normal QObject visitor (i.e. assume all @qdict values
34
+ * have the QType expected by the QOM object type)
35
* @errp: if an error occurs, a pointer to an area to store the error
36
*
37
* Create an instance of the user creatable object that is defined by
38
@@ -XXX,XX +XXX,XX @@ Object *user_creatable_add_type(const char *type, const char *id,
39
* ID from the key 'id'. The remaining entries in @qdict are used to
40
* initialize the object properties.
41
*/
42
-void user_creatable_add_dict(QDict *qdict, Error **errp);
43
+void user_creatable_add_dict(QDict *qdict, bool keyval, Error **errp);
44
45
/**
46
* user_creatable_add_opts:
47
diff --git a/qemu-storage-daemon.c b/qemu-storage-daemon.c
48
index XXXXXXX..XXXXXXX 100644
49
--- a/qemu-storage-daemon.c
50
+++ b/qemu-storage-daemon.c
51
@@ -XXX,XX +XXX,XX @@ static void process_options(int argc, char *argv[])
52
QemuOpts *opts;
53
const char *type;
54
QDict *args;
55
- QObject *ret_data = NULL;
56
57
/* FIXME The keyval parser rejects 'help' arguments, so we must
58
* unconditionall try QemuOpts first. */
59
@@ -XXX,XX +XXX,XX @@ static void process_options(int argc, char *argv[])
60
qemu_opts_del(opts);
61
62
args = keyval_parse(optarg, "qom-type", &error_fatal);
63
- qmp_object_add(args, &ret_data, &error_fatal);
64
+ user_creatable_add_dict(args, true, &error_fatal);
65
qobject_unref(args);
66
- qobject_unref(ret_data);
67
break;
68
}
69
default:
70
diff --git a/qom/object_interfaces.c b/qom/object_interfaces.c
71
index XXXXXXX..XXXXXXX 100644
72
--- a/qom/object_interfaces.c
73
+++ b/qom/object_interfaces.c
74
@@ -XXX,XX +XXX,XX @@ out:
75
return obj;
19
}
76
}
20
77
21
+# tests whether $IMGPROTO is specified as an unsupported image protocol for a test
78
-void user_creatable_add_dict(QDict *qdict, Error **errp)
22
+#
79
+void user_creatable_add_dict(QDict *qdict, bool keyval, Error **errp)
23
+_unsupported_proto()
80
{
24
+{
81
Visitor *v;
25
+ for f; do
82
Object *obj;
26
+ if [ "$f" = "$IMGPROTO" ]; then
83
@@ -XXX,XX +XXX,XX @@ void user_creatable_add_dict(QDict *qdict, Error **errp)
27
+ _notrun "not suitable for this image protocol: $IMGPROTO"
84
}
28
+ return
85
qdict_del(qdict, "id");
29
+ fi
86
30
+ done
87
- v = qobject_input_visitor_new(QOBJECT(qdict));
31
+}
88
+ if (keyval) {
32
+
89
+ v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
33
# tests whether the host OS is one of the supported OSes for a test
90
+ } else {
34
#
91
+ v = qobject_input_visitor_new(QOBJECT(qdict));
35
_supported_os()
92
+ }
93
obj = user_creatable_add_type(type, id, qdict, v, errp);
94
visit_free(v);
95
object_unref(obj);
96
diff --git a/qom/qom-qmp-cmds.c b/qom/qom-qmp-cmds.c
97
index XXXXXXX..XXXXXXX 100644
98
--- a/qom/qom-qmp-cmds.c
99
+++ b/qom/qom-qmp-cmds.c
100
@@ -XXX,XX +XXX,XX @@ void qmp_object_add(QDict *qdict, QObject **ret_data, Error **errp)
101
qobject_unref(pdict);
102
}
103
104
- user_creatable_add_dict(qdict, errp);
105
+ user_creatable_add_dict(qdict, false, errp);
106
}
107
108
void qmp_object_del(const char *id, Error **errp)
36
--
109
--
37
1.8.3.1
110
2.25.3
38
111
39
112
diff view generated by jsdifflib
Deleted patch
1
This fixes the use of a parent-less BdrvChild in bdrv_open_inherit() by
2
converting it into a BlockBackend. Which is exactly what it should be,
3
image probing is an external, standalone user of a node. The requests
4
can't be considered to originate from the format driver node because
5
that one isn't even opened yet.
6
1
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
Reviewed-by: Max Reitz <mreitz@redhat.com>
9
---
10
block.c | 36 +++++++++++++++++++-----------------
11
1 file changed, 19 insertions(+), 17 deletions(-)
12
13
diff --git a/block.c b/block.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/block.c
16
+++ b/block.c
17
@@ -XXX,XX +XXX,XX @@ BlockDriver *bdrv_probe_all(const uint8_t *buf, int buf_size,
18
return drv;
19
}
20
21
-static int find_image_format(BdrvChild *file, const char *filename,
22
+static int find_image_format(BlockBackend *file, const char *filename,
23
BlockDriver **pdrv, Error **errp)
24
{
25
- BlockDriverState *bs = file->bs;
26
BlockDriver *drv;
27
uint8_t buf[BLOCK_PROBE_BUF_SIZE];
28
int ret = 0;
29
30
/* Return the raw BlockDriver * to scsi-generic devices or empty drives */
31
- if (bdrv_is_sg(bs) || !bdrv_is_inserted(bs) || bdrv_getlength(bs) == 0) {
32
+ if (blk_is_sg(file) || !blk_is_inserted(file) || blk_getlength(file) == 0) {
33
*pdrv = &bdrv_raw;
34
return ret;
35
}
36
37
- ret = bdrv_pread(file, 0, buf, sizeof(buf));
38
+ ret = blk_pread(file, 0, buf, sizeof(buf));
39
if (ret < 0) {
40
error_setg_errno(errp, -ret, "Could not read image for determining its "
41
"format");
42
@@ -XXX,XX +XXX,XX @@ QemuOptsList bdrv_runtime_opts = {
43
*
44
* Removes all processed options from *options.
45
*/
46
-static int bdrv_open_common(BlockDriverState *bs, BdrvChild *file,
47
+static int bdrv_open_common(BlockDriverState *bs, BlockBackend *file,
48
QDict *options, Error **errp)
49
{
50
int ret, open_flags;
51
@@ -XXX,XX +XXX,XX @@ static int bdrv_open_common(BlockDriverState *bs, BdrvChild *file,
52
assert(drv != NULL);
53
54
if (file != NULL) {
55
- filename = file->bs->filename;
56
+ filename = blk_bs(file)->filename;
57
} else {
58
filename = qdict_get_try_str(options, "filename");
59
}
60
@@ -XXX,XX +XXX,XX @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
61
Error **errp)
62
{
63
int ret;
64
- BdrvChild *file = NULL;
65
+ BlockBackend *file = NULL;
66
BlockDriverState *bs;
67
BlockDriver *drv = NULL;
68
const char *drvname;
69
@@ -XXX,XX +XXX,XX @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
70
qdict_del(options, "backing");
71
}
72
73
- /* Open image file without format layer. This BdrvChild is only used for
74
+ /* Open image file without format layer. This BlockBackend is only used for
75
* probing, the block drivers will do their own bdrv_open_child() for the
76
* same BDS, which is why we put the node name back into options. */
77
if ((flags & BDRV_O_PROTOCOL) == 0) {
78
- /* FIXME Shouldn't attach a child to a node that isn't opened yet. */
79
- file = bdrv_open_child(filename, options, "file", bs,
80
- &child_file, true, &local_err);
81
+ BlockDriverState *file_bs;
82
+
83
+ file_bs = bdrv_open_child_bs(filename, options, "file", bs,
84
+ &child_file, true, &local_err);
85
if (local_err) {
86
goto fail;
87
}
88
- if (file != NULL) {
89
+ if (file_bs != NULL) {
90
+ file = blk_new();
91
+ blk_insert_bs(file, file_bs);
92
+ bdrv_unref(file_bs);
93
+
94
qdict_put(options, "file",
95
- qstring_from_str(bdrv_get_node_name(file->bs)));
96
+ qstring_from_str(bdrv_get_node_name(file_bs)));
97
}
98
}
99
100
@@ -XXX,XX +XXX,XX @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
101
}
102
103
if (file) {
104
- bdrv_unref_child(bs, file);
105
+ blk_unref(file);
106
file = NULL;
107
}
108
109
@@ -XXX,XX +XXX,XX @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
110
return bs;
111
112
fail:
113
- if (file != NULL) {
114
- bdrv_unref_child(bs, file);
115
- }
116
+ blk_unref(file);
117
if (bs->file != NULL) {
118
bdrv_unref_child(bs, bs->file);
119
}
120
--
121
1.8.3.1
122
123
diff view generated by jsdifflib
Deleted patch
1
This is a function that doesn't do any option parsing, but just does
2
some basic BlockDriverState setup and calls the .bdrv_open() function of
3
the block driver.
4
1
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
Reviewed-by: Max Reitz <mreitz@redhat.com>
7
---
8
block.c | 112 +++++++++++++++++++++++++++++++++++++---------------------------
9
1 file changed, 65 insertions(+), 47 deletions(-)
10
11
diff --git a/block.c b/block.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/block.c
14
+++ b/block.c
15
@@ -XXX,XX +XXX,XX @@ out:
16
g_free(gen_node_name);
17
}
18
19
+static int bdrv_open_driver(BlockDriverState *bs, BlockDriver *drv,
20
+ const char *node_name, QDict *options,
21
+ int open_flags, Error **errp)
22
+{
23
+ Error *local_err = NULL;
24
+ int ret;
25
+
26
+ bdrv_assign_node_name(bs, node_name, &local_err);
27
+ if (local_err) {
28
+ error_propagate(errp, local_err);
29
+ return -EINVAL;
30
+ }
31
+
32
+ bs->drv = drv;
33
+ bs->opaque = g_malloc0(drv->instance_size);
34
+
35
+ if (drv->bdrv_file_open) {
36
+ assert(!drv->bdrv_needs_filename || bs->filename[0]);
37
+ ret = drv->bdrv_file_open(bs, options, open_flags, &local_err);
38
+ } else {
39
+ ret = drv->bdrv_open(bs, options, open_flags, &local_err);
40
+ }
41
+
42
+ if (ret < 0) {
43
+ if (local_err) {
44
+ error_propagate(errp, local_err);
45
+ } else if (bs->filename[0]) {
46
+ error_setg_errno(errp, -ret, "Could not open '%s'", bs->filename);
47
+ } else {
48
+ error_setg_errno(errp, -ret, "Could not open image");
49
+ }
50
+ goto free_and_fail;
51
+ }
52
+
53
+ ret = refresh_total_sectors(bs, bs->total_sectors);
54
+ if (ret < 0) {
55
+ error_setg_errno(errp, -ret, "Could not refresh total sector count");
56
+ goto free_and_fail;
57
+ }
58
+
59
+ bdrv_refresh_limits(bs, &local_err);
60
+ if (local_err) {
61
+ error_propagate(errp, local_err);
62
+ ret = -EINVAL;
63
+ goto free_and_fail;
64
+ }
65
+
66
+ assert(bdrv_opt_mem_align(bs) != 0);
67
+ assert(bdrv_min_mem_align(bs) != 0);
68
+ assert(is_power_of_2(bs->bl.request_alignment));
69
+
70
+ return 0;
71
+
72
+free_and_fail:
73
+ /* FIXME Close bs first if already opened*/
74
+ g_free(bs->opaque);
75
+ bs->opaque = NULL;
76
+ bs->drv = NULL;
77
+ return ret;
78
+}
79
+
80
QemuOptsList bdrv_runtime_opts = {
81
.name = "bdrv_common",
82
.head = QTAILQ_HEAD_INITIALIZER(bdrv_runtime_opts.head),
83
@@ -XXX,XX +XXX,XX @@ static int bdrv_open_common(BlockDriverState *bs, BlockBackend *file,
84
trace_bdrv_open_common(bs, filename ?: "", bs->open_flags,
85
drv->format_name);
86
87
- node_name = qemu_opt_get(opts, "node-name");
88
- bdrv_assign_node_name(bs, node_name, &local_err);
89
- if (local_err) {
90
- error_propagate(errp, local_err);
91
- ret = -EINVAL;
92
- goto fail_opts;
93
- }
94
-
95
bs->read_only = !(bs->open_flags & BDRV_O_RDWR);
96
97
if (use_bdrv_whitelist && !bdrv_is_whitelisted(drv, bs->read_only)) {
98
@@ -XXX,XX +XXX,XX @@ static int bdrv_open_common(BlockDriverState *bs, BlockBackend *file,
99
}
100
pstrcpy(bs->exact_filename, sizeof(bs->exact_filename), bs->filename);
101
102
- bs->drv = drv;
103
- bs->opaque = g_malloc0(drv->instance_size);
104
-
105
/* Open the image, either directly or using a protocol */
106
open_flags = bdrv_open_flags(bs, bs->open_flags);
107
- if (drv->bdrv_file_open) {
108
- assert(file == NULL);
109
- assert(!drv->bdrv_needs_filename || filename != NULL);
110
- ret = drv->bdrv_file_open(bs, options, open_flags, &local_err);
111
- } else {
112
- ret = drv->bdrv_open(bs, options, open_flags, &local_err);
113
- }
114
-
115
- if (ret < 0) {
116
- if (local_err) {
117
- error_propagate(errp, local_err);
118
- } else if (bs->filename[0]) {
119
- error_setg_errno(errp, -ret, "Could not open '%s'", bs->filename);
120
- } else {
121
- error_setg_errno(errp, -ret, "Could not open image");
122
- }
123
- goto free_and_fail;
124
- }
125
+ node_name = qemu_opt_get(opts, "node-name");
126
127
- ret = refresh_total_sectors(bs, bs->total_sectors);
128
+ assert(!drv->bdrv_file_open || file == NULL);
129
+ ret = bdrv_open_driver(bs, drv, node_name, options, open_flags, errp);
130
if (ret < 0) {
131
- error_setg_errno(errp, -ret, "Could not refresh total sector count");
132
- goto free_and_fail;
133
- }
134
-
135
- bdrv_refresh_limits(bs, &local_err);
136
- if (local_err) {
137
- error_propagate(errp, local_err);
138
- ret = -EINVAL;
139
- goto free_and_fail;
140
+ goto fail_opts;
141
}
142
143
- assert(bdrv_opt_mem_align(bs) != 0);
144
- assert(bdrv_min_mem_align(bs) != 0);
145
- assert(is_power_of_2(bs->bl.request_alignment));
146
-
147
qemu_opts_del(opts);
148
return 0;
149
150
-free_and_fail:
151
- g_free(bs->opaque);
152
- bs->opaque = NULL;
153
- bs->drv = NULL;
154
fail_opts:
155
qemu_opts_del(opts);
156
return ret;
157
--
158
1.8.3.1
159
160
diff view generated by jsdifflib
Deleted patch
1
We should not try to assign a not yet opened node as the backing file,
2
because as soon as the permission system is added it will fail. The
3
just added bdrv_new_open_driver() function is the right tool to open a
4
file with an internal driver, use it.
5
1
6
In case anyone wonders whether that magic fake backing file to trigger a
7
special action on 'commit' actually works today: No, not for me. One
8
reason is that we've been adding a raw format driver on top for several
9
years now and raw doesn't support commit. Other reasons include that the
10
backing file isn't writable and the driver doesn't support reopen, and
11
it's also size 0 and the driver doesn't support bdrv_truncate. All of
12
these are easily fixable, but then 'commit' ended up in an infinite loop
13
deep in the vvfat code for me, so I thought I'd best leave it alone. I'm
14
not really sure what it was supposed to do anyway.
15
16
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
17
Reviewed-by: Max Reitz <mreitz@redhat.com>
18
---
19
block/vvfat.c | 10 +++++-----
20
1 file changed, 5 insertions(+), 5 deletions(-)
21
22
diff --git a/block/vvfat.c b/block/vvfat.c
23
index XXXXXXX..XXXXXXX 100644
24
--- a/block/vvfat.c
25
+++ b/block/vvfat.c
26
@@ -XXX,XX +XXX,XX @@ static void write_target_close(BlockDriverState *bs) {
27
28
static BlockDriver vvfat_write_target = {
29
.format_name = "vvfat_write_target",
30
+ .instance_size = sizeof(void*),
31
.bdrv_co_pwritev = write_target_commit,
32
.bdrv_close = write_target_close,
33
};
34
@@ -XXX,XX +XXX,XX @@ static int enable_write_target(BlockDriverState *bs, Error **errp)
35
unlink(s->qcow_filename);
36
#endif
37
38
- backing = bdrv_new();
39
+ backing = bdrv_new_open_driver(&vvfat_write_target, NULL, BDRV_O_ALLOW_RDWR,
40
+ &error_abort);
41
+ *(void**) backing->opaque = s;
42
+
43
bdrv_set_backing_hd(s->bs, backing);
44
bdrv_unref(backing);
45
46
- s->bs->backing->bs->drv = &vvfat_write_target;
47
- s->bs->backing->bs->opaque = g_new(void *, 1);
48
- *(void**)s->bs->backing->bs->opaque = s;
49
-
50
return 0;
51
52
err:
53
--
54
1.8.3.1
55
56
diff view generated by jsdifflib