1
The following changes since commit 6d9dd5fb9d0e9f4a174f53a0e20a39fbe809c71e:
1
The following changes since commit 16aaacb307ed607b9780c12702c44f0fe52edc7e:
2
2
3
Merge remote-tracking branch 'remotes/armbru/tags/pull-qobject-2018-07-27-v2' into staging (2018-07-30 09:55:47 +0100)
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
6
7
git://repo.or.cz/qemu/kevin.git tags/for-upstream
7
git://repo.or.cz/qemu/kevin.git tags/for-upstream
8
8
9
for you to fetch changes up to 1239ac241fe170bb9fcf0be74bfff04f6f1c2560:
9
for you to fetch changes up to eaae29ef89d498d0eac553c77b554f310a47f809:
10
10
11
qemu-iotests: Test query-blockstats with -drive and -blockdev (2018-07-30 15:35:37 +0200)
11
qemu-storage-daemon: Fix non-string --object properties (2020-04-30 17:51:07 +0200)
12
12
13
----------------------------------------------------------------
13
----------------------------------------------------------------
14
Block layer patches:
14
Block layer patches:
15
15
16
- qemu-img convert -C is now required to enable copy offloading
16
- Fix resize (extending) of short overlays
17
- file-posix: Fix write_zeroes with unmap on block devices (would fall
17
- nvme: introduce PMR support from NVMe 1.4 spec
18
back to explicit writes on recent kernels)
18
- qemu-storage-daemon: Fix non-string --object properties
19
- Fix query-blockstats interface for use with -blockdev
20
- Minor fixes and documentation updates
21
19
22
----------------------------------------------------------------
20
----------------------------------------------------------------
23
Fam Zheng (6):
21
Alberto Garcia (1):
24
file-posix: Handle EINTR in preallocation=full write
22
qcow2: Add incompatibility note between backing files and raw external data files
25
docs: Describe using images in writing iotests
26
iotests: Don't lock /dev/null in 226
27
Revert "qemu-img: Document copy offloading implications with -S and -c"
28
qemu-img: Add -C option for convert with copy offloading
29
iotests: Add test for 'qemu-img convert -C' compatibility
30
23
31
KONRAD Frederic (1):
24
Andrzej Jakowski (1):
32
qcow: fix a reference leak
25
nvme: introduce PMR support from NVMe 1.4 spec
33
26
34
Kevin Wolf (5):
27
Kevin Wolf (12):
35
block: Fix documentation for BDRV_REQ_MAY_UNMAP
28
block: Add flags to BlockDriver.bdrv_co_truncate()
36
file-posix: Fix write_zeroes with unmap on block devices
29
block: Add flags to bdrv(_co)_truncate()
37
block/qapi: Add 'qdev' field to query-blockstats result
30
block-backend: Add flags to blk_truncate()
38
block/qapi: Include anonymous BBs in query-blockstats
31
qcow2: Support BDRV_REQ_ZERO_WRITE for truncate
39
qemu-iotests: Test query-blockstats with -drive and -blockdev
32
raw-format: Support BDRV_REQ_ZERO_WRITE for truncate
33
file-posix: Support BDRV_REQ_ZERO_WRITE for truncate
34
block: truncate: Don't make backing file data visible
35
iotests: Filter testfiles out in filter_img_info()
36
iotests: Test committing to short backing file
37
qcow2: Forward ZERO_WRITE flag for full preallocation
38
qom: Factor out user_creatable_add_dict()
39
qemu-storage-daemon: Fix non-string --object properties
40
40
41
Leonid Bloch (1):
41
Paolo Bonzini (1):
42
qcow2: A grammar fix in conflicting cache sizing error message
42
qemu-iotests: allow qcow2 external discarded clusters to contain stale data
43
43
44
qapi/block-core.json | 14 +++-
44
docs/interop/qcow2.txt | 3 +
45
include/block/block.h | 11 +--
45
hw/block/nvme.h | 2 +
46
block/file-posix.c | 62 ++++++++++----
46
include/block/block.h | 5 +-
47
block/qapi.c | 16 +++-
47
include/block/block_int.h | 10 +-
48
block/qcow.c | 1 +
48
include/block/nvme.h | 172 ++++++++++++++++++++++++++
49
block/qcow2.c | 2 +-
49
include/qom/object_interfaces.h | 16 +++
50
qemu-img.c | 21 ++++-
50
include/sysemu/block-backend.h | 2 +-
51
docs/devel/testing.rst | 11 +++
51
block.c | 3 +-
52
qemu-img-cmds.hx | 2 +-
52
block/block-backend.c | 4 +-
53
qemu-img.texi | 14 ++--
53
block/commit.c | 4 +-
54
tests/qemu-iotests/082 | 8 ++
54
block/crypto.c | 7 +-
55
tests/qemu-iotests/082.out | 11 +++
55
block/file-posix.c | 6 +-
56
tests/qemu-iotests/103.out | 4 +-
56
block/file-win32.c | 2 +-
57
tests/qemu-iotests/137.out | 2 +-
57
block/gluster.c | 1 +
58
tests/qemu-iotests/226 | 4 +-
58
block/io.c | 43 ++++++-
59
tests/qemu-iotests/227 | 101 ++++++++++++++++++++++
59
block/iscsi.c | 2 +-
60
tests/qemu-iotests/227.out | 205 +++++++++++++++++++++++++++++++++++++++++++++
60
block/mirror.c | 2 +-
61
tests/qemu-iotests/group | 1 +
61
block/nfs.c | 3 +-
62
18 files changed, 449 insertions(+), 41 deletions(-)
62
block/parallels.c | 6 +-
63
create mode 100755 tests/qemu-iotests/227
63
block/qcow.c | 4 +-
64
create mode 100644 tests/qemu-iotests/227.out
64
block/qcow2-cluster.c | 2 +-
65
block/qcow2-refcount.c | 2 +-
66
block/qcow2.c | 73 +++++++++--
67
block/qed.c | 3 +-
68
block/raw-format.c | 6 +-
69
block/rbd.c | 1 +
70
block/sheepdog.c | 4 +-
71
block/ssh.c | 2 +-
72
block/vdi.c | 2 +-
73
block/vhdx-log.c | 2 +-
74
block/vhdx.c | 6 +-
75
block/vmdk.c | 8 +-
76
block/vpc.c | 2 +-
77
blockdev.c | 2 +-
78
hw/block/nvme.c | 109 ++++++++++++++++
79
qemu-img.c | 2 +-
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
65
96
97
diff view generated by jsdifflib
1
From: Fam Zheng <famz@redhat.com>
1
From: Alberto Garcia <berto@igalia.com>
2
2
3
Cc: qemu-stable@nongnu.org
3
Backing files and raw external data files are mutually exclusive.
4
Signed-off-by: Fam Zheng <famz@redhat.com>
4
The documentation of the raw external data bit (in autoclear_features)
5
already indicates that, but we should also mention it on the other
6
side.
7
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>
11
Reviewed-by: Eric Blake <eblake@redhat.com>
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
---
13
---
7
block/file-posix.c | 3 +++
14
docs/interop/qcow2.txt | 3 +++
8
1 file changed, 3 insertions(+)
15
1 file changed, 3 insertions(+)
9
16
10
diff --git a/block/file-posix.c b/block/file-posix.c
17
diff --git a/docs/interop/qcow2.txt b/docs/interop/qcow2.txt
11
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
12
--- a/block/file-posix.c
19
--- a/docs/interop/qcow2.txt
13
+++ b/block/file-posix.c
20
+++ b/docs/interop/qcow2.txt
14
@@ -XXX,XX +XXX,XX @@ static int handle_aiocb_truncate(RawPosixAIOData *aiocb)
21
@@ -XXX,XX +XXX,XX @@ The first cluster of a qcow2 image contains the file header:
15
num = MIN(left, 65536);
22
is stored (NB: The string is not null terminated). 0 if the
16
result = write(fd, buf, num);
23
image doesn't have a backing file.
17
if (result < 0) {
24
18
+ if (errno == EINTR) {
25
+ Note: backing files are incompatible with raw external data
19
+ continue;
26
+ files (auto-clear feature bit 1).
20
+ }
27
+
21
result = -errno;
28
16 - 19: backing_file_size
22
error_setg_errno(errp, -result,
29
Length of the backing file name in bytes. Must not be
23
"Could not write zeros for preallocation");
30
longer than 1023 bytes. Undefined if the image doesn't have
24
--
31
--
25
2.13.6
32
2.25.3
26
33
27
34
diff view generated by jsdifflib
1
From: Fam Zheng <famz@redhat.com>
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
2
3
Signed-off-by: Fam Zheng <famz@redhat.com>
3
Test 244 checks the expected behavior of qcow2 external data files
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.
9
10
This fixes docker tests on RHEL8.
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>
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
16
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
---
17
---
6
tests/qemu-iotests/082 | 8 ++++++++
18
tests/qemu-iotests/244 | 10 ++++++++--
7
tests/qemu-iotests/082.out | 11 +++++++++++
19
tests/qemu-iotests/244.out | 9 ++++++---
8
2 files changed, 19 insertions(+)
20
2 files changed, 14 insertions(+), 5 deletions(-)
9
21
10
diff --git a/tests/qemu-iotests/082 b/tests/qemu-iotests/082
22
diff --git a/tests/qemu-iotests/244 b/tests/qemu-iotests/244
11
index XXXXXXX..XXXXXXX 100755
23
index XXXXXXX..XXXXXXX 100755
12
--- a/tests/qemu-iotests/082
24
--- a/tests/qemu-iotests/244
13
+++ b/tests/qemu-iotests/082
25
+++ b/tests/qemu-iotests/244
14
@@ -XXX,XX +XXX,XX @@ run_qemu_img convert -o help
26
@@ -XXX,XX +XXX,XX @@ $QEMU_IO -c 'read -P 0 0 1M' \
15
run_qemu_img convert -O bochs -o help
16
17
echo
27
echo
18
+echo === convert: -C and other options ===
28
$QEMU_IO -c 'read -P 0 0 1M' \
19
+
29
-c 'read -P 0x11 1M 1M' \
20
+# Adding the help option to a command without other -o options
30
- -c 'read -P 0 2M 2M' \
21
+run_qemu_img convert -C -S 4k -O $IMGFMT "$TEST_IMG" "$TEST_IMG".target
31
-c 'read -P 0x11 4M 1M' \
22
+run_qemu_img convert -C -S 8k -O $IMGFMT "$TEST_IMG" "$TEST_IMG".target
32
-c 'read -P 0 5M 1M' \
23
+run_qemu_img convert -C -c -O $IMGFMT "$TEST_IMG" "$TEST_IMG".target
33
-f raw "$TEST_IMG.data" |
24
+
34
@@ -XXX,XX +XXX,XX @@ $QEMU_IO -c 'read -P 0 0 1M' \
25
+echo
35
-f $IMGFMT "$TEST_IMG" |
26
echo === amend: Options specified more than once ===
36
_filter_qemu_io
27
37
28
# Last -f should win
38
+# Discarded clusters are only marked as such in the qcow2 metadata, but
29
diff --git a/tests/qemu-iotests/082.out b/tests/qemu-iotests/082.out
39
+# they can contain stale data in the external data file. Instead, zero
40
+# clusters must be zeroed in the external data file too.
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
30
index XXXXXXX..XXXXXXX 100644
52
index XXXXXXX..XXXXXXX 100644
31
--- a/tests/qemu-iotests/082.out
53
--- a/tests/qemu-iotests/244.out
32
+++ b/tests/qemu-iotests/082.out
54
+++ b/tests/qemu-iotests/244.out
33
@@ -XXX,XX +XXX,XX @@ size Virtual disk size
55
@@ -XXX,XX +XXX,XX @@ read 1048576/1048576 bytes at offset 0
34
Testing: convert -O bochs -o help
56
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
35
qemu-img: Format driver 'bochs' does not support image creation
57
read 1048576/1048576 bytes at offset 1048576
36
58
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
37
+=== convert: -C and other options ===
59
-read 2097152/2097152 bytes at offset 2097152
38
+
60
-2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
39
+Testing: convert -C -S 4k -O qcow2 TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.target
61
read 1048576/1048576 bytes at offset 4194304
40
+qemu-img: Cannot enable copy offloading when -S is used
62
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
41
+
63
read 1048576/1048576 bytes at offset 5242880
42
+Testing: convert -C -S 8k -O qcow2 TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.target
64
@@ -XXX,XX +XXX,XX @@ read 1048576/1048576 bytes at offset 1048576
43
+qemu-img: Cannot enable copy offloading when -S is used
65
read 4194304/4194304 bytes at offset 2097152
44
+
66
4 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
45
+Testing: convert -C -c -O qcow2 TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.target
67
46
+qemu-img: Cannot enable copy offloading when -c is used
68
-Images are identical.
47
+
69
+read 1048576/1048576 bytes at offset 0
48
=== amend: Options specified more than once ===
70
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
49
71
+read 1048576/1048576 bytes at offset 1048576
50
Testing: amend -f foo -f qcow2 -o lazy_refcounts=on TEST_DIR/t.qcow2
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 ===
51
--
78
--
52
2.13.6
79
2.25.3
53
80
54
81
diff view generated by jsdifflib
New patch
1
1
This adds a new BdrvRequestFlags parameter to the .bdrv_co_truncate()
2
driver callbacks, and a supported_truncate_flags field in
3
BlockDriverState that allows drivers to advertise support for request
4
flags in the context of truncate.
5
6
For now, we always pass 0 and no drivers declare support for any flag.
7
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
10
Reviewed-by: Alberto Garcia <berto@igalia.com>
11
Reviewed-by: Max Reitz <mreitz@redhat.com>
12
Message-Id: <20200424125448.63318-2-kwolf@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
---
15
include/block/block_int.h | 10 +++++++++-
16
block/crypto.c | 3 ++-
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 =
74
diff --git a/block/file-posix.c b/block/file-posix.c
75
index XXXXXXX..XXXXXXX 100644
76
--- a/block/file-posix.c
77
+++ b/block/file-posix.c
78
@@ -XXX,XX +XXX,XX @@ raw_regular_truncate(BlockDriverState *bs, int fd, int64_t offset,
79
80
static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset,
81
bool exact, PreallocMode prealloc,
82
- Error **errp)
83
+ BdrvRequestFlags flags, Error **errp)
84
{
85
BDRVRawState *s = bs->opaque;
86
struct stat st;
87
diff --git a/block/file-win32.c b/block/file-win32.c
88
index XXXXXXX..XXXXXXX 100644
89
--- a/block/file-win32.c
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;
133
+ }
134
+ ret = drv->bdrv_co_truncate(bs, offset, exact, prealloc, flags, errp);
135
} else if (bs->file && drv->is_filter) {
136
ret = bdrv_co_truncate(bs->file, offset, exact, prealloc, errp);
137
} else {
138
diff --git a/block/iscsi.c b/block/iscsi.c
139
index XXXXXXX..XXXXXXX 100644
140
--- a/block/iscsi.c
141
+++ b/block/iscsi.c
142
@@ -XXX,XX +XXX,XX @@ static void iscsi_reopen_commit(BDRVReopenState *reopen_state)
143
144
static int coroutine_fn iscsi_co_truncate(BlockDriverState *bs, int64_t offset,
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
}
264
--
265
2.25.3
266
267
diff view generated by jsdifflib
1
BDRV_REQ_MAY_UNMAP in a write_zeroes request does not only allow the
1
Now that block drivers can support flags for .bdrv_co_truncate, expose
2
driver to unmap the blocks, but it actively requests that the blocks be
2
the parameter in the node level interfaces bdrv_co_truncate() and
3
unmapped afterwards if at all possible.
3
bdrv_truncate().
4
4
5
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>
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>
6
---
11
---
7
include/block/block.h | 11 ++++++-----
12
include/block/block.h | 5 +++--
8
1 file changed, 6 insertions(+), 5 deletions(-)
13
block/block-backend.c | 2 +-
14
block/crypto.c | 2 +-
15
block/io.c | 12 +++++++-----
16
block/parallels.c | 6 +++---
17
block/qcow.c | 4 ++--
18
block/qcow2-refcount.c | 2 +-
19
block/qcow2.c | 15 +++++++++------
20
block/raw-format.c | 2 +-
21
block/vhdx-log.c | 2 +-
22
block/vhdx.c | 2 +-
23
block/vmdk.c | 2 +-
24
tests/test-block-iothread.c | 6 +++---
25
13 files changed, 34 insertions(+), 28 deletions(-)
9
26
10
diff --git a/include/block/block.h b/include/block/block.h
27
diff --git a/include/block/block.h b/include/block/block.h
11
index XXXXXXX..XXXXXXX 100644
28
index XXXXXXX..XXXXXXX 100644
12
--- a/include/block/block.h
29
--- a/include/block/block.h
13
+++ b/include/block/block.h
30
+++ b/include/block/block.h
14
@@ -XXX,XX +XXX,XX @@ typedef struct BlockFragInfo {
31
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs,
15
typedef enum {
32
void bdrv_refresh_filename(BlockDriverState *bs);
16
BDRV_REQ_COPY_ON_READ = 0x1,
33
17
BDRV_REQ_ZERO_WRITE = 0x2,
34
int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
18
- /* The BDRV_REQ_MAY_UNMAP flag is used to indicate that the block driver
35
- PreallocMode prealloc, Error **errp);
19
- * is allowed to optimize a write zeroes request by unmapping (discarding)
36
+ PreallocMode prealloc, BdrvRequestFlags flags,
20
- * blocks if it is guaranteed that the result will read back as
37
+ Error **errp);
21
- * zeroes. The flag is only passed to the driver if the block device is
38
int bdrv_truncate(BdrvChild *child, int64_t offset, bool exact,
22
- * opened with BDRV_O_UNMAP.
39
- PreallocMode prealloc, Error **errp);
23
+
40
+ PreallocMode prealloc, BdrvRequestFlags flags, Error **errp);
24
+ /*
41
25
+ * The BDRV_REQ_MAY_UNMAP flag is used in write_zeroes requests to indicate
42
int64_t bdrv_nb_sectors(BlockDriverState *bs);
26
+ * that the block driver should unmap (discard) blocks if it is guaranteed
43
int64_t bdrv_getlength(BlockDriverState *bs);
27
+ * that the result will read back as zeroes. The flag is only passed to the
44
diff --git a/block/block-backend.c b/block/block-backend.c
28
+ * driver if the block device is opened with BDRV_O_UNMAP.
45
index XXXXXXX..XXXXXXX 100644
29
*/
46
--- a/block/block-backend.c
30
BDRV_REQ_MAY_UNMAP = 0x4,
47
+++ b/block/block-backend.c
31
48
@@ -XXX,XX +XXX,XX @@ int blk_truncate(BlockBackend *blk, int64_t offset, bool exact,
49
return -ENOMEDIUM;
50
}
51
52
- return bdrv_truncate(blk->root, offset, exact, prealloc, errp);
53
+ return bdrv_truncate(blk->root, offset, exact, prealloc, 0, errp);
54
}
55
56
int blk_save_vmstate(BlockBackend *blk, const uint8_t *buf,
57
diff --git a/block/crypto.c b/block/crypto.c
58
index XXXXXXX..XXXXXXX 100644
59
--- a/block/crypto.c
60
+++ b/block/crypto.c
61
@@ -XXX,XX +XXX,XX @@ block_crypto_co_truncate(BlockDriverState *bs, int64_t offset, bool exact,
62
63
offset += payload_offset;
64
65
- return bdrv_co_truncate(bs->file, offset, exact, prealloc, errp);
66
+ return bdrv_co_truncate(bs->file, offset, exact, prealloc, 0, errp);
67
}
68
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
};
129
diff --git a/block/parallels.c b/block/parallels.c
130
index XXXXXXX..XXXXXXX 100644
131
--- a/block/parallels.c
132
+++ b/block/parallels.c
133
@@ -XXX,XX +XXX,XX @@ static int64_t allocate_clusters(BlockDriverState *bs, int64_t sector_num,
134
} else {
135
ret = bdrv_truncate(bs->file,
136
(s->data_end + space) << BDRV_SECTOR_BITS,
137
- false, PREALLOC_MODE_OFF, NULL);
138
+ false, PREALLOC_MODE_OFF, 0, NULL);
139
}
140
if (ret < 0) {
141
return ret;
142
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn parallels_co_check(BlockDriverState *bs,
143
* That means we have to pass exact=true.
144
*/
145
ret = bdrv_truncate(bs->file, res->image_end_offset, true,
146
- PREALLOC_MODE_OFF, &local_err);
147
+ PREALLOC_MODE_OFF, 0, &local_err);
148
if (ret < 0) {
149
error_report_err(local_err);
150
res->check_errors++;
151
@@ -XXX,XX +XXX,XX @@ static void parallels_close(BlockDriverState *bs)
152
153
/* errors are ignored, so we might as well pass exact=true */
154
bdrv_truncate(bs->file, s->data_end << BDRV_SECTOR_BITS, true,
155
- PREALLOC_MODE_OFF, NULL);
156
+ PREALLOC_MODE_OFF, 0, NULL);
157
}
158
159
g_free(s->bat_dirty_bmap);
160
diff --git a/block/qcow.c b/block/qcow.c
161
index XXXXXXX..XXXXXXX 100644
162
--- a/block/qcow.c
163
+++ b/block/qcow.c
164
@@ -XXX,XX +XXX,XX @@ static int get_cluster_offset(BlockDriverState *bs,
165
return -E2BIG;
166
}
167
ret = bdrv_truncate(bs->file, cluster_offset + s->cluster_size,
168
- false, PREALLOC_MODE_OFF, NULL);
169
+ false, PREALLOC_MODE_OFF, 0, NULL);
170
if (ret < 0) {
171
return ret;
172
}
173
@@ -XXX,XX +XXX,XX @@ static int qcow_make_empty(BlockDriverState *bs)
174
l1_length) < 0)
175
return -1;
176
ret = bdrv_truncate(bs->file, s->l1_table_offset + l1_length, false,
177
- PREALLOC_MODE_OFF, NULL);
178
+ PREALLOC_MODE_OFF, 0, NULL);
179
if (ret < 0)
180
return ret;
181
182
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
183
index XXXXXXX..XXXXXXX 100644
184
--- a/block/qcow2-refcount.c
185
+++ b/block/qcow2-refcount.c
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);
194
goto resize_fail;
195
diff --git a/block/qcow2.c b/block/qcow2.c
196
index XXXXXXX..XXXXXXX 100644
197
--- a/block/qcow2.c
198
+++ b/block/qcow2.c
199
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn preallocate_co(BlockDriverState *bs, uint64_t offset,
200
mode = PREALLOC_MODE_OFF;
201
}
202
ret = bdrv_co_truncate(s->data_file, host_offset + cur_bytes, false,
203
- mode, errp);
204
+ mode, 0, errp);
205
if (ret < 0) {
206
return ret;
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)) {
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);
255
goto fail;
256
diff --git a/block/raw-format.c b/block/raw-format.c
257
index XXXXXXX..XXXXXXX 100644
258
--- a/block/raw-format.c
259
+++ b/block/raw-format.c
260
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset,
261
262
s->size = offset;
263
offset += s->offset;
264
- return bdrv_co_truncate(bs->file, offset, exact, prealloc, errp);
265
+ return bdrv_co_truncate(bs->file, offset, exact, prealloc, 0, errp);
266
}
267
268
static void raw_eject(BlockDriverState *bs, bool eject_flag)
269
diff --git a/block/vhdx-log.c b/block/vhdx-log.c
270
index XXXXXXX..XXXXXXX 100644
271
--- a/block/vhdx-log.c
272
+++ b/block/vhdx-log.c
273
@@ -XXX,XX +XXX,XX @@ static int vhdx_log_flush(BlockDriverState *bs, BDRVVHDXState *s,
274
goto exit;
275
}
276
ret = bdrv_truncate(bs->file, new_file_size, false,
277
- PREALLOC_MODE_OFF, NULL);
278
+ PREALLOC_MODE_OFF, 0, NULL);
279
if (ret < 0) {
280
goto exit;
281
}
282
diff --git a/block/vhdx.c b/block/vhdx.c
283
index XXXXXXX..XXXXXXX 100644
284
--- a/block/vhdx.c
285
+++ b/block/vhdx.c
286
@@ -XXX,XX +XXX,XX @@ static int vhdx_allocate_block(BlockDriverState *bs, BDRVVHDXState *s,
287
}
288
289
return bdrv_truncate(bs->file, *new_offset + s->block_size, false,
290
- PREALLOC_MODE_OFF, NULL);
291
+ PREALLOC_MODE_OFF, 0, NULL);
292
}
293
294
/*
295
diff --git a/block/vmdk.c b/block/vmdk.c
296
index XXXXXXX..XXXXXXX 100644
297
--- a/block/vmdk.c
298
+++ b/block/vmdk.c
299
@@ -XXX,XX +XXX,XX @@ vmdk_co_pwritev_compressed(BlockDriverState *bs, uint64_t offset,
300
}
301
length = QEMU_ALIGN_UP(length, BDRV_SECTOR_SIZE);
302
ret = bdrv_truncate(s->extents[i].file, length, false,
303
- PREALLOC_MODE_OFF, NULL);
304
+ PREALLOC_MODE_OFF, 0, NULL);
305
if (ret < 0) {
306
return ret;
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;
32
--
334
--
33
2.13.6
335
2.25.3
34
336
35
337
diff view generated by jsdifflib
New patch
1
1
Now that node level interface bdrv_truncate() supports passing request
2
flags to the block driver, expose this on the BlockBackend level, too.
3
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>
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>
10
---
11
include/sysemu/block-backend.h | 2 +-
12
block.c | 3 ++-
13
block/block-backend.c | 4 ++--
14
block/commit.c | 4 ++--
15
block/crypto.c | 2 +-
16
block/mirror.c | 2 +-
17
block/qcow2.c | 4 ++--
18
block/qed.c | 2 +-
19
block/vdi.c | 2 +-
20
block/vhdx.c | 4 ++--
21
block/vmdk.c | 6 +++---
22
block/vpc.c | 2 +-
23
blockdev.c | 2 +-
24
qemu-img.c | 2 +-
25
qemu-io-cmds.c | 2 +-
26
15 files changed, 22 insertions(+), 21 deletions(-)
27
28
diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h
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);
41
diff --git a/block.c b/block.c
42
index XXXXXXX..XXXXXXX 100644
43
--- a/block.c
44
+++ b/block.c
45
@@ -XXX,XX +XXX,XX @@ static int64_t create_file_fallback_truncate(BlockBackend *blk,
46
int64_t size;
47
int ret;
48
49
- ret = blk_truncate(blk, minimum_size, false, PREALLOC_MODE_OFF, &local_err);
50
+ ret = blk_truncate(blk, minimum_size, false, PREALLOC_MODE_OFF, 0,
51
+ &local_err);
52
if (ret < 0 && ret != -ENOTSUP) {
53
error_propagate(errp, local_err);
54
return ret;
55
diff --git a/block/block-backend.c b/block/block-backend.c
56
index XXXXXXX..XXXXXXX 100644
57
--- a/block/block-backend.c
58
+++ b/block/block-backend.c
59
@@ -XXX,XX +XXX,XX @@ int blk_pwrite_compressed(BlockBackend *blk, int64_t offset, const void *buf,
60
}
61
62
int blk_truncate(BlockBackend *blk, int64_t offset, bool exact,
63
- PreallocMode prealloc, Error **errp)
64
+ PreallocMode prealloc, BdrvRequestFlags flags, Error **errp)
65
{
66
if (!blk_is_available(blk)) {
67
error_setg(errp, "No medium inserted");
68
return -ENOMEDIUM;
69
}
70
71
- return bdrv_truncate(blk->root, offset, exact, prealloc, 0, errp);
72
+ return bdrv_truncate(blk->root, offset, exact, prealloc, flags, errp);
73
}
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);
98
diff --git a/block/crypto.c b/block/crypto.c
99
index XXXXXXX..XXXXXXX 100644
100
--- a/block/crypto.c
101
+++ b/block/crypto.c
102
@@ -XXX,XX +XXX,XX @@ static ssize_t block_crypto_init_func(QCryptoBlock *block,
103
* which will be used by the crypto header
104
*/
105
return blk_truncate(data->blk, data->size + headerlen, false,
106
- data->prealloc, errp);
107
+ data->prealloc, 0, errp);
108
}
109
110
111
diff --git a/block/mirror.c b/block/mirror.c
112
index XXXXXXX..XXXXXXX 100644
113
--- a/block/mirror.c
114
+++ b/block/mirror.c
115
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn mirror_run(Job *job, Error **errp)
116
117
if (s->bdev_length > base_length) {
118
ret = blk_truncate(s->target, s->bdev_length, false,
119
- PREALLOC_MODE_OFF, NULL);
120
+ PREALLOC_MODE_OFF, 0, NULL);
121
if (ret < 0) {
122
goto immediate_exit;
123
}
124
diff --git a/block/qcow2.c b/block/qcow2.c
125
index XXXXXXX..XXXXXXX 100644
126
--- a/block/qcow2.c
127
+++ b/block/qcow2.c
128
@@ -XXX,XX +XXX,XX @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp)
129
130
/* Okay, now that we have a valid image, let's give it the right size */
131
ret = blk_truncate(blk, qcow2_opts->size, false, qcow2_opts->preallocation,
132
- errp);
133
+ 0, errp);
134
if (ret < 0) {
135
error_prepend(errp, "Could not resize image: ");
136
goto out;
137
@@ -XXX,XX +XXX,XX @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts,
138
* Amending image options should ensure that the image has
139
* exactly the given new values, so pass exact=true here.
140
*/
141
- ret = blk_truncate(blk, new_size, true, PREALLOC_MODE_OFF, errp);
142
+ ret = blk_truncate(blk, new_size, true, PREALLOC_MODE_OFF, 0, errp);
143
blk_unref(blk);
144
if (ret < 0) {
145
return ret;
146
diff --git a/block/qed.c b/block/qed.c
147
index XXXXXXX..XXXXXXX 100644
148
--- a/block/qed.c
149
+++ b/block/qed.c
150
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_qed_co_create(BlockdevCreateOptions *opts,
151
* The QED format associates file length with allocation status,
152
* so a new file (which is empty) must have a length of 0.
153
*/
154
- ret = blk_truncate(blk, 0, true, PREALLOC_MODE_OFF, errp);
155
+ ret = blk_truncate(blk, 0, true, PREALLOC_MODE_OFF, 0, errp);
156
if (ret < 0) {
157
goto out;
158
}
159
diff --git a/block/vdi.c b/block/vdi.c
160
index XXXXXXX..XXXXXXX 100644
161
--- a/block/vdi.c
162
+++ b/block/vdi.c
163
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vdi_co_do_create(BlockdevCreateOptions *create_options,
164
165
if (image_type == VDI_TYPE_STATIC) {
166
ret = blk_truncate(blk, offset + blocks * block_size, false,
167
- PREALLOC_MODE_OFF, errp);
168
+ PREALLOC_MODE_OFF, 0, errp);
169
if (ret < 0) {
170
error_prepend(errp, "Failed to statically allocate file");
171
goto exit;
172
diff --git a/block/vhdx.c b/block/vhdx.c
173
index XXXXXXX..XXXXXXX 100644
174
--- a/block/vhdx.c
175
+++ b/block/vhdx.c
176
@@ -XXX,XX +XXX,XX @@ static int vhdx_create_bat(BlockBackend *blk, BDRVVHDXState *s,
177
/* All zeroes, so we can just extend the file - the end of the BAT
178
* is the furthest thing we have written yet */
179
ret = blk_truncate(blk, data_file_offset, false, PREALLOC_MODE_OFF,
180
- errp);
181
+ 0, errp);
182
if (ret < 0) {
183
goto exit;
184
}
185
} else if (type == VHDX_TYPE_FIXED) {
186
ret = blk_truncate(blk, data_file_offset + image_size, false,
187
- PREALLOC_MODE_OFF, errp);
188
+ PREALLOC_MODE_OFF, 0, errp);
189
if (ret < 0) {
190
goto exit;
191
}
192
diff --git a/block/vmdk.c b/block/vmdk.c
193
index XXXXXXX..XXXXXXX 100644
194
--- a/block/vmdk.c
195
+++ b/block/vmdk.c
196
@@ -XXX,XX +XXX,XX @@ static int vmdk_init_extent(BlockBackend *blk,
197
int gd_buf_size;
198
199
if (flat) {
200
- ret = blk_truncate(blk, filesize, false, PREALLOC_MODE_OFF, errp);
201
+ ret = blk_truncate(blk, filesize, false, PREALLOC_MODE_OFF, 0, errp);
202
goto exit;
203
}
204
magic = cpu_to_be32(VMDK4_MAGIC);
205
@@ -XXX,XX +XXX,XX @@ static int vmdk_init_extent(BlockBackend *blk,
206
}
207
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
}
223
diff --git a/block/vpc.c b/block/vpc.c
224
index XXXXXXX..XXXXXXX 100644
225
--- a/block/vpc.c
226
+++ b/block/vpc.c
227
@@ -XXX,XX +XXX,XX @@ static int create_fixed_disk(BlockBackend *blk, uint8_t *buf,
228
/* Add footer to total size */
229
total_size += HEADER_SIZE;
230
231
- ret = blk_truncate(blk, total_size, false, PREALLOC_MODE_OFF, errp);
232
+ ret = blk_truncate(blk, total_size, false, PREALLOC_MODE_OFF, 0, errp);
233
if (ret < 0) {
234
return ret;
235
}
236
diff --git a/blockdev.c b/blockdev.c
237
index XXXXXXX..XXXXXXX 100644
238
--- a/blockdev.c
239
+++ b/blockdev.c
240
@@ -XXX,XX +XXX,XX @@ void qmp_block_resize(bool has_device, const char *device,
241
}
242
243
bdrv_drained_begin(bs);
244
- ret = blk_truncate(blk, size, false, PREALLOC_MODE_OFF, errp);
245
+ ret = blk_truncate(blk, size, false, PREALLOC_MODE_OFF, 0, errp);
246
bdrv_drained_end(bs);
247
248
out:
249
diff --git a/qemu-img.c b/qemu-img.c
250
index XXXXXXX..XXXXXXX 100644
251
--- a/qemu-img.c
252
+++ b/qemu-img.c
253
@@ -XXX,XX +XXX,XX @@ static int img_resize(int argc, char **argv)
254
* resizing, so pass @exact=true. It is of no use to report
255
* success when the image has not actually been resized.
256
*/
257
- ret = blk_truncate(blk, total_size, true, prealloc, &err);
258
+ ret = blk_truncate(blk, total_size, true, prealloc, 0, &err);
259
if (!ret) {
260
qprintf(quiet, "Image resized.\n");
261
} else {
262
diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
263
index XXXXXXX..XXXXXXX 100644
264
--- a/qemu-io-cmds.c
265
+++ b/qemu-io-cmds.c
266
@@ -XXX,XX +XXX,XX @@ static int truncate_f(BlockBackend *blk, int argc, char **argv)
267
* exact=true. It is better to err on the "emit more errors" side
268
* than to be overly permissive.
269
*/
270
- ret = blk_truncate(blk, offset, true, PREALLOC_MODE_OFF, &local_err);
271
+ ret = blk_truncate(blk, offset, true, PREALLOC_MODE_OFF, 0, &local_err);
272
if (ret < 0) {
273
error_report_err(local_err);
274
return ret;
275
--
276
2.25.3
277
278
diff view generated by jsdifflib
1
Consistent with query-block, query-blockstats should not only include
1
If BDRV_REQ_ZERO_WRITE is set and we're extending the image, calling
2
named BlockBackends, but also those that are anonymous, but belong to a
2
qcow2_cluster_zeroize() with flags=0 does the right thing: It doesn't
3
device model.
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>
6
Reviewed-by: Eric Blake <eblake@redhat.com>
9
Reviewed-by: Eric Blake <eblake@redhat.com>
10
Reviewed-by: Max Reitz <mreitz@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
---
12
---
8
block/qapi.c | 6 +++++-
13
block/qcow2-cluster.c | 2 +-
9
1 file changed, 5 insertions(+), 1 deletion(-)
14
block/qcow2.c | 34 ++++++++++++++++++++++++++++++++++
15
2 files changed, 35 insertions(+), 1 deletion(-)
10
16
11
diff --git a/block/qapi.c b/block/qapi.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/qapi.c
19
--- a/block/qcow2-cluster.c
14
+++ b/block/qapi.c
20
+++ b/block/qcow2-cluster.c
15
@@ -XXX,XX +XXX,XX @@ BlockStatsList *qmp_query_blockstats(bool has_query_nodes,
21
@@ -XXX,XX +XXX,XX @@ int qcow2_cluster_zeroize(BlockDriverState *bs, uint64_t offset,
16
p_next = &info->next;
22
/* Caller must pass aligned values, except at image end */
17
}
23
assert(QEMU_IS_ALIGNED(offset, s->cluster_size));
18
} else {
24
assert(QEMU_IS_ALIGNED(end_offset, s->cluster_size) ||
19
- for (blk = blk_next(NULL); blk; blk = blk_next(blk)) {
25
- end_offset == bs->total_sectors << BDRV_SECTOR_BITS);
20
+ for (blk = blk_all_next(NULL); blk; blk = blk_all_next(blk)) {
26
+ end_offset >= bs->total_sectors << BDRV_SECTOR_BITS);
21
BlockStatsList *info = g_malloc0(sizeof(*info));
27
22
AioContext *ctx = blk_get_aio_context(blk);
28
/* The zero flag is only supported by version 3 and newer */
23
BlockStats *s;
29
if (s->qcow_version < 3) {
24
char *qdev;
30
diff --git a/block/qcow2.c b/block/qcow2.c
25
31
index XXXXXXX..XXXXXXX 100644
26
+ if (!*blk_name(blk) && !blk_get_attached_dev(blk)) {
32
--- a/block/qcow2.c
27
+ continue;
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);
48
+
49
+ /*
50
+ * Use zero clusters as much as we can. qcow2_cluster_zeroize()
51
+ * requires a cluster-aligned start. The end may be unaligned if it is
52
+ * at the end of the image (which it is here).
53
+ */
54
+ ret = qcow2_cluster_zeroize(bs, zero_start, offset - zero_start, 0);
55
+ if (ret < 0) {
56
+ error_setg_errno(errp, -ret, "Failed to zero out new clusters");
57
+ goto fail;
58
+ }
59
+
60
+ /* Write explicit zeros for the unaligned head */
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);
72
+ if (ret < 0) {
73
+ error_setg_errno(errp, -ret, "Failed to zero out the new area");
74
+ goto fail;
28
+ }
75
+ }
76
+ }
77
+ }
29
+
78
+
30
aio_context_acquire(ctx);
79
if (prealloc != PREALLOC_MODE_OFF) {
31
s = bdrv_query_bds_stats(blk_bs(blk), true);
80
/* Flush metadata before actually changing the image size */
32
s->has_device = true;
81
ret = qcow2_write_caches(bs);
33
--
82
--
34
2.13.6
83
2.25.3
35
84
36
85
diff view generated by jsdifflib
1
Like for query-block, the client needs to identify which BlockBackend
1
The raw format driver can simply forward the flag and let its bs->file
2
the returned data is for. Anonymous BlockBackends are identified by the
2
child take care of actually providing the zeros.
3
device model they are attached to. Add a 'qdev' field that contains the
4
qdev ID or QOM path of the attached device model.
5
3
6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
Reviewed-by: Max Reitz <mreitz@redhat.com>
7
Reviewed-by: Eric Blake <eblake@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>
8
---
10
---
9
qapi/block-core.json | 14 ++++++++++----
11
block/raw-format.c | 4 +++-
10
block/qapi.c | 10 ++++++++++
12
1 file changed, 3 insertions(+), 1 deletion(-)
11
2 files changed, 20 insertions(+), 4 deletions(-)
12
13
13
diff --git a/qapi/block-core.json b/qapi/block-core.json
14
diff --git a/block/raw-format.c b/block/raw-format.c
14
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
15
--- a/qapi/block-core.json
16
--- a/block/raw-format.c
16
+++ b/qapi/block-core.json
17
+++ b/block/raw-format.c
17
@@ -XXX,XX +XXX,XX @@
18
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset,
18
#
19
19
# @node-name: The node name of the device. (Since 2.3)
20
s->size = offset;
20
#
21
offset += s->offset;
21
+# @qdev: The qdev ID, or if no ID is assigned, the QOM path of the block
22
- return bdrv_co_truncate(bs->file, offset, exact, prealloc, 0, errp);
22
+# device. (since 3.0)
23
+ return bdrv_co_truncate(bs->file, offset, exact, prealloc, flags, errp);
23
+#
24
}
24
# @stats: A @BlockDeviceStats for the device.
25
25
#
26
static void raw_eject(BlockDriverState *bs, bool eject_flag)
26
# @parent: This describes the file block device if it has one.
27
@@ -XXX,XX +XXX,XX @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags,
27
@@ -XXX,XX +XXX,XX @@
28
bs->supported_zero_flags = BDRV_REQ_WRITE_UNCHANGED |
28
# Since: 0.14.0
29
((BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK) &
29
##
30
bs->file->bs->supported_zero_flags);
30
{ 'struct': 'BlockStats',
31
+ bs->supported_truncate_flags = bs->file->bs->supported_truncate_flags &
31
- 'data': {'*device': 'str', '*node-name': 'str',
32
+ BDRV_REQ_ZERO_WRITE;
32
+ 'data': {'*device': 'str', '*qdev': 'str', '*node-name': 'str',
33
33
'stats': 'BlockDeviceStats',
34
if (bs->probed && !bdrv_is_read_only(bs)) {
34
'*parent': 'BlockStats',
35
bdrv_refresh_filename(bs->file->bs);
35
'*backing': 'BlockStats'} }
36
@@ -XXX,XX +XXX,XX @@
37
# "idle_time_ns":2953431879,
38
# "account_invalid":true,
39
# "account_failed":false
40
-# }
41
+# },
42
+# "qdev": "/machine/unattached/device[23]"
43
# },
44
# {
45
# "device":"ide1-cd0",
46
@@ -XXX,XX +XXX,XX @@
47
# "wr_merged":0,
48
# "account_invalid":false,
49
# "account_failed":false
50
-# }
51
+# },
52
+# "qdev": "/machine/unattached/device[24]"
53
# },
54
# {
55
# "device":"floppy0",
56
@@ -XXX,XX +XXX,XX @@
57
# "wr_merged":0,
58
# "account_invalid":false,
59
# "account_failed":false
60
-# }
61
+# },
62
+# "qdev": "/machine/unattached/device[16]"
63
# },
64
# {
65
# "device":"sd0",
66
diff --git a/block/qapi.c b/block/qapi.c
67
index XXXXXXX..XXXXXXX 100644
68
--- a/block/qapi.c
69
+++ b/block/qapi.c
70
@@ -XXX,XX +XXX,XX @@ BlockStatsList *qmp_query_blockstats(bool has_query_nodes,
71
BlockStatsList *info = g_malloc0(sizeof(*info));
72
AioContext *ctx = blk_get_aio_context(blk);
73
BlockStats *s;
74
+ char *qdev;
75
76
aio_context_acquire(ctx);
77
s = bdrv_query_bds_stats(blk_bs(blk), true);
78
s->has_device = true;
79
s->device = g_strdup(blk_name(blk));
80
+
81
+ qdev = blk_get_attached_dev_id(blk);
82
+ if (qdev && *qdev) {
83
+ s->has_qdev = true;
84
+ s->qdev = qdev;
85
+ } else {
86
+ g_free(qdev);
87
+ }
88
+
89
bdrv_query_blk_stats(s->stats, blk);
90
aio_context_release(ctx);
91
92
--
36
--
93
2.13.6
37
2.25.3
94
38
95
39
diff view generated by jsdifflib
1
The BLKDISCARD ioctl doesn't guarantee that the discarded blocks read as
1
For regular files, we always get BDRV_REQ_ZERO_WRITE behaviour from the
2
all-zero afterwards, so don't try to abuse it for zero writing. We try
2
OS, so we can advertise the flag and just ignore it.
3
to only use this if BLKDISCARDZEROES tells us that it is safe, but this
4
is unreliable on older kernels and a constant 0 in newer kernels. In
5
other words, this code path is never actually used with newer kernels,
6
so we don't even try to unmap while writing zeros.
7
8
This patch removes the abuse of discard for writing zeroes from
9
file-posix and instead adds a new function that uses interfaces that are
10
actually meant to deallocate and zero out at the same time. Only if
11
those fail, it falls back to zeroing out without unmap. We never fall
12
back to a discard operation any more that may or may not result in
13
zeros.
14
3
15
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>
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
8
Message-Id: <20200424125448.63318-7-kwolf@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
16
---
10
---
17
block/file-posix.c | 59 ++++++++++++++++++++++++++++++++++++++++--------------
11
block/file-posix.c | 4 ++++
18
1 file changed, 44 insertions(+), 15 deletions(-)
12
1 file changed, 4 insertions(+)
19
13
20
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
21
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
22
--- a/block/file-posix.c
16
--- a/block/file-posix.c
23
+++ b/block/file-posix.c
17
+++ b/block/file-posix.c
24
@@ -XXX,XX +XXX,XX @@ static int raw_open_common(BlockDriverState *bs, QDict *options,
18
@@ -XXX,XX +XXX,XX @@ static int raw_open_common(BlockDriverState *bs, QDict *options,
25
}
26
#endif
19
#endif
27
20
28
- bs->supported_zero_flags = s->discard_zeroes ? BDRV_REQ_MAY_UNMAP : 0;
21
bs->supported_zero_flags = BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK;
29
+ bs->supported_zero_flags = BDRV_REQ_MAY_UNMAP;
22
+ if (S_ISREG(st.st_mode)) {
23
+ /* When extending regular files, we get zeros from the OS */
24
+ bs->supported_truncate_flags = BDRV_REQ_ZERO_WRITE;
25
+ }
30
ret = 0;
26
ret = 0;
31
fail:
27
fail:
32
if (filename && (bdrv_flags & BDRV_O_TEMPORARY)) {
28
if (filename && (bdrv_flags & BDRV_O_TEMPORARY)) {
33
@@ -XXX,XX +XXX,XX @@ static ssize_t handle_aiocb_write_zeroes(RawPosixAIOData *aiocb)
34
return -ENOTSUP;
35
}
36
37
+static ssize_t handle_aiocb_write_zeroes_unmap(RawPosixAIOData *aiocb)
38
+{
39
+ BDRVRawState *s G_GNUC_UNUSED = aiocb->bs->opaque;
40
+ int ret;
41
+
42
+ /* First try to write zeros and unmap at the same time */
43
+
44
+#ifdef CONFIG_FALLOCATE_PUNCH_HOLE
45
+ ret = do_fallocate(s->fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
46
+ aiocb->aio_offset, aiocb->aio_nbytes);
47
+ if (ret != -ENOTSUP) {
48
+ return ret;
49
+ }
50
+#endif
51
+
52
+#ifdef CONFIG_XFS
53
+ if (s->is_xfs) {
54
+ /* xfs_discard() guarantees that the discarded area reads as all-zero
55
+ * afterwards, so we can use it here. */
56
+ return xfs_discard(s, aiocb->aio_offset, aiocb->aio_nbytes);
57
+ }
58
+#endif
59
+
60
+ /* If we couldn't manage to unmap while guaranteed that the area reads as
61
+ * all-zero afterwards, just write zeroes without unmapping */
62
+ ret = handle_aiocb_write_zeroes(aiocb);
63
+ return ret;
64
+}
65
+
66
#ifndef HAVE_COPY_FILE_RANGE
67
static off_t copy_file_range(int in_fd, off_t *in_off, int out_fd,
68
off_t *out_off, size_t len, unsigned int flags)
69
@@ -XXX,XX +XXX,XX @@ static int aio_worker(void *arg)
70
case QEMU_AIO_WRITE_ZEROES:
71
ret = handle_aiocb_write_zeroes(aiocb);
72
break;
73
+ case QEMU_AIO_WRITE_ZEROES | QEMU_AIO_DISCARD:
74
+ ret = handle_aiocb_write_zeroes_unmap(aiocb);
75
+ break;
76
case QEMU_AIO_COPY_RANGE:
77
ret = handle_aiocb_copy_range(aiocb);
78
break;
79
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn raw_co_pwrite_zeroes(
80
int bytes, BdrvRequestFlags flags)
81
{
82
BDRVRawState *s = bs->opaque;
83
+ int operation = QEMU_AIO_WRITE_ZEROES;
84
85
- if (!(flags & BDRV_REQ_MAY_UNMAP)) {
86
- return paio_submit_co(bs, s->fd, offset, NULL, bytes,
87
- QEMU_AIO_WRITE_ZEROES);
88
- } else if (s->discard_zeroes) {
89
- return paio_submit_co(bs, s->fd, offset, NULL, bytes,
90
- QEMU_AIO_DISCARD);
91
+ if (flags & BDRV_REQ_MAY_UNMAP) {
92
+ operation |= QEMU_AIO_DISCARD;
93
}
94
- return -ENOTSUP;
95
+
96
+ return paio_submit_co(bs, s->fd, offset, NULL, bytes, operation);
97
}
98
99
static int raw_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
100
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int hdev_co_pwrite_zeroes(BlockDriverState *bs,
101
int64_t offset, int bytes, BdrvRequestFlags flags)
102
{
103
BDRVRawState *s = bs->opaque;
104
+ int operation = QEMU_AIO_WRITE_ZEROES | QEMU_AIO_BLKDEV;
105
int rc;
106
107
rc = fd_open(bs);
108
if (rc < 0) {
109
return rc;
110
}
111
- if (!(flags & BDRV_REQ_MAY_UNMAP)) {
112
- return paio_submit_co(bs, s->fd, offset, NULL, bytes,
113
- QEMU_AIO_WRITE_ZEROES|QEMU_AIO_BLKDEV);
114
- } else if (s->discard_zeroes) {
115
- return paio_submit_co(bs, s->fd, offset, NULL, bytes,
116
- QEMU_AIO_DISCARD|QEMU_AIO_BLKDEV);
117
+
118
+ if (flags & BDRV_REQ_MAY_UNMAP) {
119
+ operation |= QEMU_AIO_DISCARD;
120
}
121
- return -ENOTSUP;
122
+
123
+ return paio_submit_co(bs, s->fd, offset, NULL, bytes, operation);
124
}
125
126
static int coroutine_fn hdev_co_create_opts(const char *filename, QemuOpts *opts,
127
--
29
--
128
2.13.6
30
2.25.3
129
31
130
32
diff view generated by jsdifflib
1
From: Fam Zheng <famz@redhat.com>
1
When extending the size of an image that has a backing file larger than
2
its old size, make sure that the backing file data doesn't become
3
visible in the guest, but the added area is properly zeroed out.
2
4
3
Signed-off-by: Fam Zheng <famz@redhat.com>
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.
29
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>
33
Reviewed-by: Max Reitz <mreitz@redhat.com>
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
34
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
---
35
---
6
qemu-img.c | 21 +++++++++++++++++----
36
block/io.c | 25 +++++++++++++++++++++++++
7
qemu-img-cmds.hx | 2 +-
37
1 file changed, 25 insertions(+)
8
qemu-img.texi | 8 +++++++-
9
3 files changed, 25 insertions(+), 6 deletions(-)
10
38
11
diff --git a/qemu-img.c b/qemu-img.c
39
diff --git a/block/io.c b/block/io.c
12
index XXXXXXX..XXXXXXX 100644
40
index XXXXXXX..XXXXXXX 100644
13
--- a/qemu-img.c
41
--- a/block/io.c
14
+++ b/qemu-img.c
42
+++ b/block/io.c
15
@@ -XXX,XX +XXX,XX @@ static int img_convert(int argc, char **argv)
43
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
16
skip_create = false, progress = false, tgt_image_opts = false;
44
goto out;
17
int64_t ret = -EINVAL;
18
bool force_share = false;
19
+ bool explict_min_sparse = false;
20
21
ImgConvertState s = (ImgConvertState) {
22
/* Need at least 4k of zeros for sparse detection */
23
.min_sparse = 8,
24
- .copy_range = true,
25
+ .copy_range = false,
26
.buf_sectors = IO_BUF_SIZE / BDRV_SECTOR_SIZE,
27
.wr_in_order = true,
28
.num_coroutines = 8,
29
@@ -XXX,XX +XXX,XX @@ static int img_convert(int argc, char **argv)
30
{"target-image-opts", no_argument, 0, OPTION_TARGET_IMAGE_OPTS},
31
{0, 0, 0, 0}
32
};
33
- c = getopt_long(argc, argv, ":hf:O:B:co:l:S:pt:T:qnm:WU",
34
+ c = getopt_long(argc, argv, ":hf:O:B:Cco:l:S:pt:T:qnm:WU",
35
long_options, NULL);
36
if (c == -1) {
37
break;
38
@@ -XXX,XX +XXX,XX @@ static int img_convert(int argc, char **argv)
39
case 'B':
40
out_baseimg = optarg;
41
break;
42
+ case 'C':
43
+ s.copy_range = true;
44
+ break;
45
case 'c':
46
s.compressed = true;
47
- s.copy_range = false;
48
break;
49
case 'o':
50
if (!is_valid_option_list(optarg)) {
51
@@ -XXX,XX +XXX,XX @@ static int img_convert(int argc, char **argv)
52
}
53
54
s.min_sparse = sval / BDRV_SECTOR_SIZE;
55
- s.copy_range = false;
56
+ explict_min_sparse = true;
57
break;
58
}
59
case 'p':
60
@@ -XXX,XX +XXX,XX @@ static int img_convert(int argc, char **argv)
61
goto fail_getopt;
62
}
45
}
63
46
64
+ if (s.compressed && s.copy_range) {
47
+ /*
65
+ error_report("Cannot enable copy offloading when -c is used");
48
+ * If the image has a backing file that is large enough that it would
66
+ goto fail_getopt;
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;
59
+
60
+ backing_len = bdrv_getlength(backing_bs(bs));
61
+ if (backing_len < 0) {
62
+ ret = backing_len;
63
+ error_setg_errno(errp, -ret, "Could not get backing file size");
64
+ goto out;
65
+ }
66
+
67
+ if (backing_len > old_size) {
68
+ flags |= BDRV_REQ_ZERO_WRITE;
69
+ }
67
+ }
70
+ }
68
+
71
+
69
+ if (explict_min_sparse && s.copy_range) {
72
if (drv->bdrv_co_truncate) {
70
+ error_report("Cannot enable copy offloading when -S is used");
73
if (flags & ~bs->supported_truncate_flags) {
71
+ goto fail_getopt;
74
error_setg(errp, "Block driver does not support requested flags");
72
+ }
73
+
74
if (tgt_image_opts && !skip_create) {
75
error_report("--target-image-opts requires use of -n flag");
76
goto fail_getopt;
77
diff --git a/qemu-img-cmds.hx b/qemu-img-cmds.hx
78
index XXXXXXX..XXXXXXX 100644
79
--- a/qemu-img-cmds.hx
80
+++ b/qemu-img-cmds.hx
81
@@ -XXX,XX +XXX,XX @@ STEXI
82
ETEXI
83
84
DEF("convert", img_convert,
85
- "convert [--object objectdef] [--image-opts] [--target-image-opts] [-U] [-c] [-p] [-q] [-n] [-f fmt] [-t cache] [-T src_cache] [-O output_fmt] [-B backing_file] [-o options] [-l snapshot_param] [-S sparse_size] [-m num_coroutines] [-W] filename [filename2 [...]] output_filename")
86
+ "convert [--object objectdef] [--image-opts] [--target-image-opts] [-U] [-C] [-c] [-p] [-q] [-n] [-f fmt] [-t cache] [-T src_cache] [-O output_fmt] [-B backing_file] [-o options] [-l snapshot_param] [-S sparse_size] [-m num_coroutines] [-W] filename [filename2 [...]] output_filename")
87
STEXI
88
@item convert [--object @var{objectdef}] [--image-opts] [--target-image-opts] [-U] [-c] [-p] [-q] [-n] [-f @var{fmt}] [-t @var{cache}] [-T @var{src_cache}] [-O @var{output_fmt}] [-B @var{backing_file}] [-o @var{options}] [-l @var{snapshot_param}] [-S @var{sparse_size}] [-m @var{num_coroutines}] [-W] @var{filename} [@var{filename2} [...]] @var{output_filename}
89
ETEXI
90
diff --git a/qemu-img.texi b/qemu-img.texi
91
index XXXXXXX..XXXXXXX 100644
92
--- a/qemu-img.texi
93
+++ b/qemu-img.texi
94
@@ -XXX,XX +XXX,XX @@ Number of parallel coroutines for the convert process
95
Allow out-of-order writes to the destination. This option improves performance,
96
but is only recommended for preallocated devices like host devices or other
97
raw block devices.
98
+@item -C
99
+Try to use copy offloading to move data from source image to target. This may
100
+improve performance if the data is remote, such as with NFS or iSCSI backends,
101
+but will not automatically sparsify zero sectors, and may result in a fully
102
+allocated target image depending on the host support for getting allocation
103
+information.
104
@end table
105
106
Parameters to dd subcommand:
107
@@ -XXX,XX +XXX,XX @@ Error on reading data
108
109
@end table
110
111
-@item convert [--object @var{objectdef}] [--image-opts] [--target-image-opts] [-U] [-c] [-p] [-q] [-n] [-f @var{fmt}] [-t @var{cache}] [-T @var{src_cache}] [-O @var{output_fmt}] [-B @var{backing_file}] [-o @var{options}] [-l @var{snapshot_param}] [-S @var{sparse_size}] [-m @var{num_coroutines}] [-W] @var{filename} [@var{filename2} [...]] @var{output_filename}
112
+@item convert [--object @var{objectdef}] [--image-opts] [--target-image-opts] [-U] [-C] [-c] [-p] [-q] [-n] [-f @var{fmt}] [-t @var{cache}] [-T @var{src_cache}] [-O @var{output_fmt}] [-B @var{backing_file}] [-o @var{options}] [-l @var{snapshot_param}] [-S @var{sparse_size}] [-m @var{num_coroutines}] [-W] @var{filename} [@var{filename2} [...]] @var{output_filename}
113
114
Convert the disk image @var{filename} or a snapshot @var{snapshot_param}
115
to disk image @var{output_filename} using format @var{output_fmt}. It can be optionally compressed (@code{-c}
116
--
75
--
117
2.13.6
76
2.25.3
118
77
119
78
diff view generated by jsdifflib
1
From: Fam Zheng <famz@redhat.com>
1
We want to keep TEST_IMG for the full path of the main test image, but
2
filter_testfiles() must be called for other test images before replacing
3
other things like the image format because the test directory path could
4
contain the format as a substring.
2
5
3
This reverts commit eb461485f4558e362fab905735b50987505bca44.
6
Insert a filter_testfiles() call between both.
4
7
5
Now that we introduce an explicit option, these implicit rules are not
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
used.
9
Reviewed-by: Max Reitz <mreitz@redhat.com>
7
10
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
8
Signed-off-by: Fam Zheng <famz@redhat.com>
11
Message-Id: <20200424125448.63318-9-kwolf@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
13
---
11
qemu-img.texi | 6 ++----
14
tests/qemu-iotests/iotests.py | 5 +++--
12
1 file changed, 2 insertions(+), 4 deletions(-)
15
1 file changed, 3 insertions(+), 2 deletions(-)
13
16
14
diff --git a/qemu-img.texi b/qemu-img.texi
17
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
15
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
16
--- a/qemu-img.texi
19
--- a/tests/qemu-iotests/iotests.py
17
+++ b/qemu-img.texi
20
+++ b/tests/qemu-iotests/iotests.py
18
@@ -XXX,XX +XXX,XX @@ will enumerate information about backing files in a disk image chain. Refer
21
@@ -XXX,XX +XXX,XX @@ def filter_img_info(output, filename):
19
below for further description.
22
for line in output.split('\n'):
20
23
if 'disk size' in line or 'actual-size' in line:
21
@item -c
24
continue
22
-indicates that target image must be compressed (qcow format only). If this
25
- line = line.replace(filename, 'TEST_IMG') \
23
-option is used, copy offloading will not be attempted.
26
- .replace(imgfmt, 'IMGFMT')
24
+indicates that target image must be compressed (qcow format only)
27
+ line = line.replace(filename, 'TEST_IMG')
25
28
+ line = filter_testfiles(line)
26
@item -h
29
+ line = line.replace(imgfmt, 'IMGFMT')
27
with or without a command shows help and lists the supported formats
30
line = re.sub('iters: [0-9]+', 'iters: XXX', line)
28
@@ -XXX,XX +XXX,XX @@ in case both @var{-q} and @var{-p} options are used.
31
line = re.sub('uuid: [-a-f0-9]+', 'uuid: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX', line)
29
indicates the consecutive number of bytes that must contain only zeros
32
line = re.sub('cid: [0-9]+', 'cid: XXXXXXXXXX', line)
30
for qemu-img to create a sparse image during conversion. This value is rounded
31
down to the nearest 512 bytes. You may use the common size suffixes like
32
-@code{k} for kilobytes. If this option is used, copy offloading will not be
33
-attempted.
34
+@code{k} for kilobytes.
35
36
@item -t @var{cache}
37
specifies the cache mode that should be used with the (destination) file. See
38
--
33
--
39
2.13.6
34
2.25.3
40
35
41
36
diff view generated by jsdifflib
1
Make sure that query-blockstats returns information for every
2
BlockBackend that is named or attached to a device model (or both).
3
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
1
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
Reviewed-by: Eric Blake <eblake@redhat.com>
2
Message-Id: <20200424125448.63318-10-kwolf@redhat.com>
3
Reviewed-by: Max Reitz <mreitz@redhat.com>
4
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
---
6
---
8
tests/qemu-iotests/227 | 101 ++++++++++++++++++++++
7
tests/qemu-iotests/274 | 155 +++++++++++++++++++++
9
tests/qemu-iotests/227.out | 205 +++++++++++++++++++++++++++++++++++++++++++++
8
tests/qemu-iotests/274.out | 268 +++++++++++++++++++++++++++++++++++++
10
tests/qemu-iotests/group | 1 +
9
tests/qemu-iotests/group | 1 +
11
3 files changed, 307 insertions(+)
10
3 files changed, 424 insertions(+)
12
create mode 100755 tests/qemu-iotests/227
11
create mode 100755 tests/qemu-iotests/274
13
create mode 100644 tests/qemu-iotests/227.out
12
create mode 100644 tests/qemu-iotests/274.out
14
13
15
diff --git a/tests/qemu-iotests/227 b/tests/qemu-iotests/227
14
diff --git a/tests/qemu-iotests/274 b/tests/qemu-iotests/274
16
new file mode 100755
15
new file mode 100755
17
index XXXXXXX..XXXXXXX
16
index XXXXXXX..XXXXXXX
18
--- /dev/null
17
--- /dev/null
19
+++ b/tests/qemu-iotests/227
18
+++ b/tests/qemu-iotests/274
20
@@ -XXX,XX +XXX,XX @@
19
@@ -XXX,XX +XXX,XX @@
21
+#!/bin/bash
20
+#!/usr/bin/env python3
22
+#
21
+#
23
+# Test query-blockstats with different ways to create a BB
22
+# Copyright (C) 2019 Red Hat, Inc.
24
+#
25
+# Copyright (C) 2018 Red Hat, Inc.
26
+#
23
+#
27
+# 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
28
+# 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
29
+# the Free Software Foundation; either version 2 of the License, or
26
+# the Free Software Foundation; either version 2 of the License, or
30
+# (at your option) any later version.
27
+# (at your option) any later version.
...
...
35
+# GNU General Public License for more details.
32
+# GNU General Public License for more details.
36
+#
33
+#
37
+# 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
38
+# 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/>.
39
+#
36
+#
40
+
37
+# Creator/Owner: Kevin Wolf <kwolf@redhat.com>
41
+# creator
38
+#
42
+owner=kwolf@redhat.com
39
+# Some tests for short backing files and short overlays
43
+
40
+
44
+seq=$(basename $0)
41
+import iotests
45
+echo "QA output created by $seq"
42
+
46
+
43
+iotests.verify_image_format(supported_fmts=['qcow2'])
47
+here=$PWD
44
+iotests.verify_platform(['linux'])
48
+status=1    # failure is the default!
45
+
49
+
46
+size_short = 1 * 1024 * 1024
50
+_cleanup()
47
+size_long = 2 * 1024 * 1024
51
+{
48
+size_diff = size_long - size_short
52
+ _cleanup_test_img
49
+
53
+}
50
+def create_chain() -> None:
54
+trap "_cleanup; exit \$status" 0 1 2 3 15
51
+ iotests.qemu_img_log('create', '-f', iotests.imgfmt, base,
55
+
52
+ str(size_long))
56
+# get standard environment, filters and checks
53
+ iotests.qemu_img_log('create', '-f', iotests.imgfmt, '-b', base, mid,
57
+. ./common.rc
54
+ str(size_short))
58
+. ./common.filter
55
+ iotests.qemu_img_log('create', '-f', iotests.imgfmt, '-b', mid, top,
59
+
56
+ str(size_long))
60
+_supported_fmt generic
57
+
61
+_supported_proto file
58
+ iotests.qemu_io_log('-c', 'write -P 1 0 %d' % size_long, base)
62
+_supported_os Linux
59
+
63
+
60
+def create_vm() -> iotests.VM:
64
+function do_run_qemu()
61
+ vm = iotests.VM()
65
+{
62
+ vm.add_blockdev('file,filename=%s,node-name=base-file' % base)
66
+ echo Testing: "$@"
63
+ vm.add_blockdev('%s,file=base-file,node-name=base' % iotests.imgfmt)
67
+ $QEMU -nographic -qmp-pretty stdio -serial none "$@"
64
+ vm.add_blockdev('file,filename=%s,node-name=mid-file' % mid)
68
+ echo
65
+ vm.add_blockdev('%s,file=mid-file,node-name=mid,backing=base'
69
+}
66
+ % iotests.imgfmt)
70
+
67
+ vm.add_drive(top, 'backing=mid,node-name=top')
71
+function run_qemu()
68
+ return vm
72
+{
69
+
73
+ do_run_qemu "$@" 2>&1 | _filter_testdir | _filter_qmp \
70
+with iotests.FilePath('base') as base, \
74
+ | _filter_qemu | _filter_imgfmt \
71
+ iotests.FilePath('mid') as mid, \
75
+ | _filter_generated_node_ids
72
+ iotests.FilePath('top') as top:
76
+}
73
+
77
+
74
+ iotests.log('== Commit tests ==')
78
+echo
75
+
79
+echo '=== blockstats with -drive if=virtio ==='
76
+ create_chain()
80
+echo
77
+
81
+
78
+ iotests.log('=== Check visible data ===')
82
+run_qemu -drive driver=null-co,if=virtio <<EOF
79
+
83
+{ "execute": "qmp_capabilities" }
80
+ iotests.qemu_io_log('-c', 'read -P 1 0 %d' % size_short, top)
84
+{ "execute": "query-blockstats"}
81
+ iotests.qemu_io_log('-c', 'read -P 0 %d %d' % (size_short, size_diff), top)
85
+{ "execute": "quit" }
82
+
86
+EOF
83
+ iotests.log('=== Checking allocation status ===')
87
+
84
+
88
+echo
85
+ iotests.qemu_io_log('-c', 'alloc 0 %d' % size_short,
89
+echo '=== blockstats with -drive if=none ==='
86
+ '-c', 'alloc %d %d' % (size_short, size_diff),
90
+echo
87
+ base)
91
+
88
+
92
+run_qemu -drive driver=null-co,if=none <<EOF
89
+ iotests.qemu_io_log('-c', 'alloc 0 %d' % size_short,
93
+{ "execute": "qmp_capabilities" }
90
+ '-c', 'alloc %d %d' % (size_short, size_diff),
94
+{ "execute": "query-blockstats"}
91
+ mid)
95
+{ "execute": "quit" }
92
+
96
+EOF
93
+ iotests.qemu_io_log('-c', 'alloc 0 %d' % size_short,
97
+
94
+ '-c', 'alloc %d %d' % (size_short, size_diff),
98
+echo
95
+ top)
99
+echo '=== blockstats with -blockdev ==='
96
+
100
+echo
97
+ iotests.log('=== Checking map ===')
101
+
98
+
102
+run_qemu -blockdev driver=null-co,node-name=null <<EOF
99
+ iotests.qemu_img_log('map', '--output=json', base)
103
+{ "execute": "qmp_capabilities" }
100
+ iotests.qemu_img_log('map', '--output=human', base)
104
+{ "execute": "query-blockstats"}
101
+ iotests.qemu_img_log('map', '--output=json', mid)
105
+{ "execute": "quit" }
102
+ iotests.qemu_img_log('map', '--output=human', mid)
106
+EOF
103
+ iotests.qemu_img_log('map', '--output=json', top)
107
+
104
+ iotests.qemu_img_log('map', '--output=human', top)
108
+echo
105
+
109
+echo '=== blockstats with -blockdev and -device ==='
106
+ iotests.log('=== Testing qemu-img commit (top -> mid) ===')
110
+echo
107
+
111
+
108
+ iotests.qemu_img_log('commit', top)
112
+run_qemu -blockdev driver=null-co,node-name=null -device virtio-blk,drive=null,id=virtio0 <<EOF
109
+ iotests.img_info_log(mid)
113
+{ "execute": "qmp_capabilities" }
110
+ iotests.qemu_io_log('-c', 'read -P 1 0 %d' % size_short, mid)
114
+{ "execute": "query-blockstats"}
111
+ iotests.qemu_io_log('-c', 'read -P 0 %d %d' % (size_short, size_diff), mid)
115
+{ "execute": "quit" }
112
+
116
+EOF
113
+ iotests.log('=== Testing HMP commit (top -> mid) ===')
117
+
114
+
118
+# success, all done
115
+ create_chain()
119
+echo "*** done"
116
+ with create_vm() as vm:
120
+rm -f $seq.full
117
+ vm.launch()
121
+status=0
118
+ vm.qmp_log('human-monitor-command', command_line='commit drive0')
122
diff --git a/tests/qemu-iotests/227.out b/tests/qemu-iotests/227.out
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
123
new file mode 100644
176
new file mode 100644
124
index XXXXXXX..XXXXXXX
177
index XXXXXXX..XXXXXXX
125
--- /dev/null
178
--- /dev/null
126
+++ b/tests/qemu-iotests/227.out
179
+++ b/tests/qemu-iotests/274.out
127
@@ -XXX,XX +XXX,XX @@
180
@@ -XXX,XX +XXX,XX @@
128
+QA output created by 227
181
+== Commit tests ==
129
+
182
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=2097152 cluster_size=65536 lazy_refcounts=off refcount_bits=16
130
+=== blockstats with -drive if=virtio ===
183
+
131
+
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
132
+Testing: -drive driver=null-co,if=virtio
185
+
133
+{
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
134
+ QMP_VERSION
187
+
135
+}
188
+wrote 2097152/2097152 bytes at offset 0
136
+{
189
+2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
137
+ "return": {
190
+
138
+ }
191
+=== Check visible data ===
139
+}
192
+read 1048576/1048576 bytes at offset 0
140
+{
193
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
141
+ "return": [
194
+
142
+ {
195
+read 1048576/1048576 bytes at offset 1048576
143
+ "device": "virtio0",
196
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
144
+ "stats": {
197
+
145
+ "flush_total_time_ns": 0,
198
+=== Checking allocation status ===
146
+ "wr_highest_offset": 0,
199
+1048576/1048576 bytes allocated at offset 0 bytes
147
+ "wr_total_time_ns": 0,
200
+1048576/1048576 bytes allocated at offset 1 MiB
148
+ "failed_wr_operations": 0,
201
+
149
+ "failed_rd_operations": 0,
202
+0/1048576 bytes allocated at offset 0 bytes
150
+ "wr_merged": 0,
203
+0/0 bytes allocated at offset 1 MiB
151
+ "wr_bytes": 0,
204
+
152
+ "timed_stats": [
205
+0/1048576 bytes allocated at offset 0 bytes
153
+ ],
206
+0/1048576 bytes allocated at offset 1 MiB
154
+ "failed_flush_operations": 0,
207
+
155
+ "account_invalid": true,
208
+=== Checking map ===
156
+ "rd_total_time_ns": 0,
209
+[{ "start": 0, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": 327680}]
157
+ "flush_operations": 0,
210
+
158
+ "wr_operations": 0,
211
+Offset Length Mapped to File
159
+ "rd_merged": 0,
212
+0 0x200000 0x50000 TEST_DIR/PID-base
160
+ "rd_bytes": 0,
213
+
161
+ "invalid_flush_operations": 0,
214
+[{ "start": 0, "length": 1048576, "depth": 1, "zero": false, "data": true, "offset": 327680}]
162
+ "account_failed": true,
215
+
163
+ "rd_operations": 0,
216
+Offset Length Mapped to File
164
+ "invalid_wr_operations": 0,
217
+0 0x100000 0x50000 TEST_DIR/PID-base
165
+ "invalid_rd_operations": 0
218
+
166
+ },
219
+[{ "start": 0, "length": 1048576, "depth": 2, "zero": false, "data": true, "offset": 327680},
167
+ "node-name": "NODE_NAME",
220
+{ "start": 1048576, "length": 1048576, "depth": 0, "zero": true, "data": false}]
168
+ "qdev": "/machine/peripheral-anon/device[0]/virtio-backend"
221
+
169
+ }
222
+Offset Length Mapped to File
170
+ ]
223
+0 0x100000 0x50000 TEST_DIR/PID-base
171
+}
224
+
172
+{
225
+=== Testing qemu-img commit (top -> mid) ===
173
+ "return": {
226
+Image committed.
174
+ }
227
+
175
+}
228
+image: TEST_IMG
176
+{
229
+file format: IMGFMT
177
+ "timestamp": {
230
+virtual size: 2 MiB (2097152 bytes)
178
+ "seconds": TIMESTAMP,
231
+cluster_size: 65536
179
+ "microseconds": TIMESTAMP
232
+backing file: TEST_DIR/PID-base
180
+ },
233
+Format specific information:
181
+ "event": "SHUTDOWN",
234
+ compat: 1.1
182
+ "data": {
235
+ lazy refcounts: false
183
+ "guest": false
236
+ refcount bits: 16
184
+ }
237
+ corrupt: false
185
+}
238
+
186
+
239
+read 1048576/1048576 bytes at offset 0
187
+
240
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
188
+=== blockstats with -drive if=none ===
241
+
189
+
242
+read 1048576/1048576 bytes at offset 1048576
190
+Testing: -drive driver=null-co,if=none
243
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
191
+{
244
+
192
+ QMP_VERSION
245
+=== Testing HMP commit (top -> mid) ===
193
+}
246
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=2097152 cluster_size=65536 lazy_refcounts=off refcount_bits=16
194
+{
247
+
195
+ "return": {
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
196
+ }
249
+
197
+}
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
198
+{
251
+
199
+ "return": [
252
+wrote 2097152/2097152 bytes at offset 0
200
+ {
253
+2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
201
+ "device": "none0",
254
+
202
+ "stats": {
255
+{"execute": "human-monitor-command", "arguments": {"command-line": "commit drive0"}}
203
+ "flush_total_time_ns": 0,
256
+{"return": ""}
204
+ "wr_highest_offset": 0,
257
+image: TEST_IMG
205
+ "wr_total_time_ns": 0,
258
+file format: IMGFMT
206
+ "failed_wr_operations": 0,
259
+virtual size: 2 MiB (2097152 bytes)
207
+ "failed_rd_operations": 0,
260
+cluster_size: 65536
208
+ "wr_merged": 0,
261
+backing file: TEST_DIR/PID-base
209
+ "wr_bytes": 0,
262
+Format specific information:
210
+ "timed_stats": [
263
+ compat: 1.1
211
+ ],
264
+ lazy refcounts: false
212
+ "failed_flush_operations": 0,
265
+ refcount bits: 16
213
+ "account_invalid": true,
266
+ corrupt: false
214
+ "rd_total_time_ns": 0,
267
+
215
+ "flush_operations": 0,
268
+read 1048576/1048576 bytes at offset 0
216
+ "wr_operations": 0,
269
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
217
+ "rd_merged": 0,
270
+
218
+ "rd_bytes": 0,
271
+read 1048576/1048576 bytes at offset 1048576
219
+ "invalid_flush_operations": 0,
272
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
220
+ "account_failed": true,
273
+
221
+ "rd_operations": 0,
274
+=== Testing QMP active commit (top -> mid) ===
222
+ "invalid_wr_operations": 0,
275
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=2097152 cluster_size=65536 lazy_refcounts=off refcount_bits=16
223
+ "invalid_rd_operations": 0
276
+
224
+ },
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
225
+ "node-name": "NODE_NAME"
278
+
226
+ }
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
227
+ ]
280
+
228
+}
281
+wrote 2097152/2097152 bytes at offset 0
229
+{
282
+2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
230
+ "return": {
283
+
231
+ }
284
+{"execute": "block-commit", "arguments": {"auto-dismiss": false, "base-node": "mid", "device": "top", "job-id": "job0"}}
232
+}
285
+{"return": {}}
233
+{
286
+{"execute": "job-complete", "arguments": {"id": "job0"}}
234
+ "timestamp": {
287
+{"return": {}}
235
+ "seconds": TIMESTAMP,
288
+{"data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "commit"}, "event": "BLOCK_JOB_READY", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
236
+ "microseconds": TIMESTAMP
289
+{"data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "commit"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
237
+ },
290
+{"execute": "job-dismiss", "arguments": {"id": "job0"}}
238
+ "event": "SHUTDOWN",
291
+{"return": {}}
239
+ "data": {
292
+image: TEST_IMG
240
+ "guest": false
293
+file format: IMGFMT
241
+ }
294
+virtual size: 2 MiB (2097152 bytes)
242
+}
295
+cluster_size: 65536
243
+
296
+backing file: TEST_DIR/PID-base
244
+
297
+Format specific information:
245
+=== blockstats with -blockdev ===
298
+ compat: 1.1
246
+
299
+ lazy refcounts: false
247
+Testing: -blockdev driver=null-co,node-name=null
300
+ refcount bits: 16
248
+{
301
+ corrupt: false
249
+ QMP_VERSION
302
+
250
+}
303
+read 1048576/1048576 bytes at offset 0
251
+{
304
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
252
+ "return": {
305
+
253
+ }
306
+read 1048576/1048576 bytes at offset 1048576
254
+}
307
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
255
+{
308
+
256
+ "return": [
309
+== Resize tests ==
257
+ ]
310
+=== preallocation=off ===
258
+}
311
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=6442450944 cluster_size=65536 lazy_refcounts=off refcount_bits=16
259
+{
312
+
260
+ "return": {
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
261
+ }
314
+
262
+}
315
+wrote 65536/65536 bytes at offset 5368709120
263
+{
316
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
264
+ "timestamp": {
317
+
265
+ "seconds": TIMESTAMP,
318
+Image resized.
266
+ "microseconds": TIMESTAMP
319
+
267
+ },
320
+read 65536/65536 bytes at offset 5368709120
268
+ "event": "SHUTDOWN",
321
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
269
+ "data": {
322
+
270
+ "guest": false
323
+1 GiB (0x40000000) bytes not allocated at offset 0 bytes (0x0)
271
+ }
324
+7 GiB (0x1c0000000) bytes allocated at offset 1 GiB (0x40000000)
272
+}
325
+
273
+
326
+[{ "start": 0, "length": 1073741824, "depth": 1, "zero": true, "data": false},
274
+
327
+{ "start": 1073741824, "length": 7516192768, "depth": 0, "zero": true, "data": false}]
275
+=== blockstats with -blockdev and -device ===
328
+
276
+
329
+=== preallocation=metadata ===
277
+Testing: -blockdev driver=null-co,node-name=null -device virtio-blk,drive=null,id=virtio0
330
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=34359738368 cluster_size=65536 lazy_refcounts=off refcount_bits=16
278
+{
331
+
279
+ QMP_VERSION
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
280
+}
333
+
281
+{
334
+wrote 65536/65536 bytes at offset 33285996544
282
+ "return": {
335
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
283
+ }
336
+
284
+}
337
+Image resized.
285
+{
338
+
286
+ "return": [
339
+read 65536/65536 bytes at offset 33285996544
287
+ {
340
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
288
+ "device": "",
341
+
289
+ "stats": {
342
+30 GiB (0x780000000) bytes not allocated at offset 0 bytes (0x0)
290
+ "flush_total_time_ns": 0,
343
+3 GiB (0xc0000000) bytes allocated at offset 30 GiB (0x780000000)
291
+ "wr_highest_offset": 0,
344
+
292
+ "wr_total_time_ns": 0,
345
+[{ "start": 0, "length": 32212254720, "depth": 1, "zero": true, "data": false},
293
+ "failed_wr_operations": 0,
346
+{ "start": 32212254720, "length": 536870912, "depth": 0, "zero": true, "data": false, "offset": 327680},
294
+ "failed_rd_operations": 0,
347
+{ "start": 32749125632, "length": 536870912, "depth": 0, "zero": true, "data": false, "offset": 537264128},
295
+ "wr_merged": 0,
348
+{ "start": 33285996544, "length": 536870912, "depth": 0, "zero": true, "data": false, "offset": 1074200576},
296
+ "wr_bytes": 0,
349
+{ "start": 33822867456, "length": 536870912, "depth": 0, "zero": true, "data": false, "offset": 1611137024},
297
+ "timed_stats": [
350
+{ "start": 34359738368, "length": 536870912, "depth": 0, "zero": true, "data": false, "offset": 2148139008},
298
+ ],
351
+{ "start": 34896609280, "length": 536870912, "depth": 0, "zero": true, "data": false, "offset": 2685075456}]
299
+ "failed_flush_operations": 0,
352
+
300
+ "account_invalid": false,
353
+=== preallocation=falloc ===
301
+ "rd_total_time_ns": 0,
354
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=10485760 cluster_size=65536 lazy_refcounts=off refcount_bits=16
302
+ "flush_operations": 0,
355
+
303
+ "wr_operations": 0,
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
304
+ "rd_merged": 0,
357
+
305
+ "rd_bytes": 0,
358
+wrote 65536/65536 bytes at offset 9437184
306
+ "invalid_flush_operations": 0,
359
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
307
+ "account_failed": false,
360
+
308
+ "rd_operations": 0,
361
+Image resized.
309
+ "invalid_wr_operations": 0,
362
+
310
+ "invalid_rd_operations": 0
363
+read 65536/65536 bytes at offset 9437184
311
+ },
364
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
312
+ "node-name": "null",
365
+
313
+ "qdev": "/machine/peripheral/virtio0/virtio-backend"
366
+5 MiB (0x500000) bytes not allocated at offset 0 bytes (0x0)
314
+ }
367
+10 MiB (0xa00000) bytes allocated at offset 5 MiB (0x500000)
315
+ ]
368
+
316
+}
369
+[{ "start": 0, "length": 5242880, "depth": 1, "zero": true, "data": false},
317
+{
370
+{ "start": 5242880, "length": 10485760, "depth": 0, "zero": true, "data": false, "offset": 327680}]
318
+ "return": {
371
+
319
+ }
372
+=== preallocation=full ===
320
+}
373
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=16777216 cluster_size=65536 lazy_refcounts=off refcount_bits=16
321
+{
374
+
322
+ "timestamp": {
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
323
+ "seconds": TIMESTAMP,
376
+
324
+ "microseconds": TIMESTAMP
377
+wrote 65536/65536 bytes at offset 11534336
325
+ },
378
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
326
+ "event": "SHUTDOWN",
379
+
327
+ "data": {
380
+Image resized.
328
+ "guest": false
381
+
329
+ }
382
+read 65536/65536 bytes at offset 11534336
330
+}
383
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
331
+
384
+
332
+*** done
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
+
333
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
334
index XXXXXXX..XXXXXXX 100644
450
index XXXXXXX..XXXXXXX 100644
335
--- a/tests/qemu-iotests/group
451
--- a/tests/qemu-iotests/group
336
+++ b/tests/qemu-iotests/group
452
+++ b/tests/qemu-iotests/group
337
@@ -XXX,XX +XXX,XX @@
453
@@ -XXX,XX +XXX,XX @@
338
223 rw auto quick
454
270 rw backing quick
339
225 rw auto quick
455
272 rw
340
226 auto quick
456
273 backing quick
341
+227 auto quick
457
+274 rw backing
458
277 rw quick
459
279 rw backing quick
460
280 rw migration quick
342
--
461
--
343
2.13.6
462
2.25.3
344
463
345
464
diff view generated by jsdifflib
1
From: Leonid Bloch <lbloch@janustech.com>
1
The BDRV_REQ_ZERO_WRITE is currently implemented in a way that first the
2
image is possibly preallocated and then the zero flag is added to all
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.
2
6
3
Signed-off-by: Leonid Bloch <lbloch@janustech.com>
7
Instead, try to forward the BDRV_REQ_ZERO_WRITE to the protocol driver,
4
Reviewed-by: John Snow <jsnow@redhat.com>
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.
13
14
Signed-off-by: Kevin Wolf <kwolf@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>
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
18
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
---
19
---
7
block/qcow2.c | 2 +-
20
block/qcow2.c | 22 +++++++++++++++++++---
8
tests/qemu-iotests/103.out | 4 ++--
21
tests/qemu-iotests/274.out | 4 ++--
9
tests/qemu-iotests/137.out | 2 +-
22
2 files changed, 21 insertions(+), 5 deletions(-)
10
3 files changed, 4 insertions(+), 4 deletions(-)
11
23
12
diff --git a/block/qcow2.c b/block/qcow2.c
24
diff --git a/block/qcow2.c b/block/qcow2.c
13
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
14
--- a/block/qcow2.c
26
--- a/block/qcow2.c
15
+++ b/block/qcow2.c
27
+++ b/block/qcow2.c
16
@@ -XXX,XX +XXX,XX @@ static void read_cache_sizes(BlockDriverState *bs, QemuOpts *opts,
28
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
17
if (l2_cache_size_set && refcount_cache_size_set) {
29
/* Allocate the data area */
18
error_setg(errp, QCOW2_OPT_CACHE_SIZE ", " QCOW2_OPT_L2_CACHE_SIZE
30
new_file_size = allocation_start +
19
" and " QCOW2_OPT_REFCOUNT_CACHE_SIZE " may not be set "
31
nb_new_data_clusters * s->cluster_size;
20
- "the same time");
32
- /* Image file grows, so @exact does not matter */
21
+ "at the same time");
33
- ret = bdrv_co_truncate(bs->file, new_file_size, false, prealloc, 0,
22
return;
34
- errp);
23
} else if (*l2_cache_size > combined_cache_size) {
35
+ /*
24
error_setg(errp, QCOW2_OPT_L2_CACHE_SIZE " may not exceed "
36
+ * Image file grows, so @exact does not matter.
25
diff --git a/tests/qemu-iotests/103.out b/tests/qemu-iotests/103.out
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
+ }
54
if (ret < 0) {
55
error_prepend(errp, "Failed to resize underlying file: ");
56
qcow2_free_clusters(bs, allocation_start,
57
diff --git a/tests/qemu-iotests/274.out b/tests/qemu-iotests/274.out
26
index XXXXXXX..XXXXXXX 100644
58
index XXXXXXX..XXXXXXX 100644
27
--- a/tests/qemu-iotests/103.out
59
--- a/tests/qemu-iotests/274.out
28
+++ b/tests/qemu-iotests/103.out
60
+++ b/tests/qemu-iotests/274.out
29
@@ -XXX,XX +XXX,XX @@ wrote 65536/65536 bytes at offset 0
61
@@ -XXX,XX +XXX,XX @@ read 65536/65536 bytes at offset 9437184
30
62
10 MiB (0xa00000) bytes allocated at offset 5 MiB (0x500000)
31
=== Testing invalid option combinations ===
63
32
64
[{ "start": 0, "length": 5242880, "depth": 1, "zero": true, "data": false},
33
-can't open device TEST_DIR/t.IMGFMT: cache-size, l2-cache-size and refcount-cache-size may not be set the same time
65
-{ "start": 5242880, "length": 10485760, "depth": 0, "zero": true, "data": false, "offset": 327680}]
34
+can't open device TEST_DIR/t.IMGFMT: cache-size, l2-cache-size and refcount-cache-size may not be set at the same time
66
+{ "start": 5242880, "length": 10485760, "depth": 0, "zero": false, "data": true, "offset": 327680}]
35
can't open device TEST_DIR/t.IMGFMT: l2-cache-size may not exceed cache-size
67
36
can't open device TEST_DIR/t.IMGFMT: refcount-cache-size may not exceed cache-size
68
=== preallocation=full ===
37
-can't open device TEST_DIR/t.IMGFMT: cache-size, l2-cache-size and refcount-cache-size may not be set the same time
69
Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=16777216 cluster_size=65536 lazy_refcounts=off refcount_bits=16
38
+can't open device TEST_DIR/t.IMGFMT: cache-size, l2-cache-size and refcount-cache-size may not be set at the same time
70
@@ -XXX,XX +XXX,XX @@ read 65536/65536 bytes at offset 11534336
39
can't open device TEST_DIR/t.IMGFMT: L2 cache entry size must be a power of two between 512 and the cluster size (65536)
71
4 MiB (0x400000) bytes allocated at offset 8 MiB (0x800000)
40
can't open device TEST_DIR/t.IMGFMT: L2 cache entry size must be a power of two between 512 and the cluster size (65536)
72
41
can't open device TEST_DIR/t.IMGFMT: L2 cache entry size must be a power of two between 512 and the cluster size (65536)
73
[{ "start": 0, "length": 8388608, "depth": 1, "zero": true, "data": false},
42
diff --git a/tests/qemu-iotests/137.out b/tests/qemu-iotests/137.out
74
-{ "start": 8388608, "length": 4194304, "depth": 0, "zero": true, "data": false, "offset": 327680}]
43
index XXXXXXX..XXXXXXX 100644
75
+{ "start": 8388608, "length": 4194304, "depth": 0, "zero": false, "data": true, "offset": 327680}]
44
--- a/tests/qemu-iotests/137.out
76
45
+++ b/tests/qemu-iotests/137.out
77
=== preallocation=off ===
46
@@ -XXX,XX +XXX,XX @@ read 33554432/33554432 bytes at offset 0
78
Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=393216 cluster_size=65536 lazy_refcounts=off refcount_bits=16
47
=== Try setting some invalid values ===
48
49
Parameter 'lazy-refcounts' expects 'on' or 'off'
50
-cache-size, l2-cache-size and refcount-cache-size may not be set the same time
51
+cache-size, l2-cache-size and refcount-cache-size may not be set at the same time
52
l2-cache-size may not exceed cache-size
53
refcount-cache-size may not exceed cache-size
54
L2 cache size too big
55
--
79
--
56
2.13.6
80
2.25.3
57
81
58
82
diff view generated by jsdifflib
1
From: Fam Zheng <famz@redhat.com>
1
From: Andrzej Jakowski <andrzej.jakowski@linux.intel.com>
2
2
3
On my system (Fedora 28), this script reports a 'failed to get
3
This patch introduces support for PMR that has been defined as part of NVMe 1.4
4
"consistent read" lock' error. Following docs/devel/testing.rst, it's
4
spec. User can now specify a pmrdev option that should point to HostMemoryBackend.
5
better to add locking=off here.
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
Signed-off-by: Fam Zheng <famz@redhat.com>
9
Signed-off-by: Andrzej Jakowski <andrzej.jakowski@linux.intel.com>
8
Reviewed-by: Eric Blake <eblake@redhat.com>
10
Reviewed-by: Klaus Jensen <k.jensen@samsung.com>
9
Reviewed-by: John Snow <jsnow@redhat.com>
11
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
12
Message-Id: <20200330164656.9348-1-andrzej.jakowski@linux.intel.com>
13
Reviewed-by: Keith Busch <kbusch@kernel.org>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
---
15
---
12
tests/qemu-iotests/226 | 4 ++--
16
hw/block/nvme.h | 2 +
13
1 file changed, 2 insertions(+), 2 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(-)
14
22
15
diff --git a/tests/qemu-iotests/226 b/tests/qemu-iotests/226
23
diff --git a/hw/block/nvme.h b/hw/block/nvme.h
16
index XXXXXXX..XXXXXXX 100755
24
index XXXXXXX..XXXXXXX 100644
17
--- a/tests/qemu-iotests/226
25
--- a/hw/block/nvme.h
18
+++ b/tests/qemu-iotests/226
26
+++ b/hw/block/nvme.h
19
@@ -XXX,XX +XXX,XX @@ for PROTO in "file" "host_device" "host_cdrom"; do
27
@@ -XXX,XX +XXX,XX @@ typedef struct NvmeCtrl {
20
echo
28
uint64_t timestamp_set_qemu_clock_ms; /* QEMU clock time */
21
echo "== Testing RO =="
29
22
$QEMU_IO -c "open -r -o driver=$PROTO,filename=$TEST_IMG" 2>&1 | _filter_testdir | _filter_imgfmt
30
char *serial;
23
- $QEMU_IO -c "open -r -o driver=$PROTO,filename=/dev/null" 2>&1 | _filter_imgfmt
31
+ HostMemoryBackend *pmrdev;
24
+ $QEMU_IO -c "open -r -o driver=$PROTO,filename=/dev/null,locking=off" 2>&1 | _filter_imgfmt
32
+
25
echo "== Testing RW =="
33
NvmeNamespace *namespaces;
26
$QEMU_IO -c "open -o driver=$PROTO,filename=$TEST_IMG" 2>&1 | _filter_testdir | _filter_imgfmt
34
NvmeSQueue **sq;
27
- $QEMU_IO -c "open -o driver=$PROTO,filename=/dev/null" 2>&1 | _filter_imgfmt
35
NvmeCQueue **cq;
28
+ $QEMU_IO -c "open -o driver=$PROTO,filename=/dev/null,locking=off" 2>&1 | _filter_imgfmt
36
diff --git a/include/block/nvme.h b/include/block/nvme.h
29
done
37
index XXXXXXX..XXXXXXX 100644
30
38
--- a/include/block/nvme.h
31
# success, all done
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)
309
}
310
311
if (addr < sizeof(n->bar)) {
312
+ /*
313
+ * When PMRWBM bit 1 is set then read from
314
+ * from PMRSTS should ensure prior writes
315
+ * made it to persistent media
316
+ */
317
+ if (addr == 0xE08 &&
318
+ (NVME_PMRCAP_PMRWBM(n->bar.pmrcap) & 0x02)) {
319
+ qemu_ram_writeback(n->pmrdev->mr.ram_block,
320
+ 0, n->pmrdev->size);
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;
328
}
329
+
330
+ if (!n->cmb_size_mb && n->pmrdev) {
331
+ if (host_memory_backend_is_mapped(n->pmrdev)) {
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;
336
+ }
337
+
338
+ if (!is_power_of_2(n->pmrdev->size)) {
339
+ error_setg(errp, "pmr backend size needs to be power of 2 in size");
340
+ return;
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);
398
}
399
400
for (i = 0; i < n->num_namespaces; i++) {
401
@@ -XXX,XX +XXX,XX @@ static void nvme_exit(PCIDevice *pci_dev)
402
if (n->cmb_size_mb) {
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""
32
--
452
--
33
2.13.6
453
2.25.3
34
454
35
455
diff view generated by jsdifflib
1
From: Fam Zheng <famz@redhat.com>
1
The QMP handler qmp_object_add() and the implementation of --object in
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.
2
5
3
Signed-off-by: Fam Zheng <famz@redhat.com>
6
As a first step towards a fix, make qmp_object_add() a wrapper around a
4
Reviewed-by: Eric Blake <eblake@redhat.com>
7
new function user_creatable_add_dict() that can get an additional
5
Reviewed-by: John Snow <jsnow@redhat.com>
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().
11
6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
---
13
---
8
docs/devel/testing.rst | 11 +++++++++++
14
include/qom/object_interfaces.h | 12 ++++++++++++
9
1 file changed, 11 insertions(+)
15
qom/object_interfaces.c | 27 +++++++++++++++++++++++++++
16
qom/qom-qmp-cmds.c | 24 +-----------------------
17
3 files changed, 40 insertions(+), 23 deletions(-)
10
18
11
diff --git a/docs/devel/testing.rst b/docs/devel/testing.rst
19
diff --git a/include/qom/object_interfaces.h b/include/qom/object_interfaces.h
12
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
13
--- a/docs/devel/testing.rst
21
--- a/include/qom/object_interfaces.h
14
+++ b/docs/devel/testing.rst
22
+++ b/include/qom/object_interfaces.h
15
@@ -XXX,XX +XXX,XX @@ comparable library support for invoking and interacting with QEMU programs. If
23
@@ -XXX,XX +XXX,XX @@ Object *user_creatable_add_type(const char *type, const char *id,
16
you opt for Python, it is strongly recommended to write Python 3 compatible
24
const QDict *qdict,
17
code.
25
Visitor *v, Error **errp);
18
26
19
+Both Python and Bash frameworks in iotests provide helpers to manage test
27
+/**
20
+images. They can be used to create and clean up images under the test
28
+ * user_creatable_add_dict:
21
+directory. If no I/O or any protocol specific feature is needed, it is often
29
+ * @qdict: the object definition
22
+more convenient to use the pseudo block driver, ``null-co://``, as the test
30
+ * @errp: if an error occurs, a pointer to an area to store the error
23
+image, which doesn't require image creation or cleaning up. Avoid system-wide
31
+ *
24
+devices or files whenever possible, such as ``/dev/null`` or ``/dev/zero``.
32
+ * Create an instance of the user creatable object that is defined by
25
+Otherwise, image locking implications have to be considered. For example,
33
+ * @qdict. The object type is taken from the QDict key 'qom-type', its
26
+another application on the host may have locked the file, possibly leading to a
34
+ * ID from the key 'id'. The remaining entries in @qdict are used to
27
+test failure. If using such devices are explicitly desired, consider adding
35
+ * initialize the object properties.
28
+``locking=off`` option to disable image locking.
36
+ */
37
+void user_creatable_add_dict(QDict *qdict, Error **errp);
29
+
38
+
30
Docker based tests
39
/**
31
==================
40
* user_creatable_add_opts:
32
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;
56
}
57
58
+void user_creatable_add_dict(QDict *qdict, Error **errp)
59
+{
60
+ Visitor *v;
61
+ Object *obj;
62
+ g_autofree char *type = NULL;
63
+ g_autofree char *id = NULL;
64
+
65
+ type = g_strdup(qdict_get_try_str(qdict, "qom-type"));
66
+ if (!type) {
67
+ error_setg(errp, QERR_MISSING_PARAMETER, "qom-type");
68
+ return;
69
+ }
70
+ qdict_del(qdict, "qom-type");
71
+
72
+ id = g_strdup(qdict_get_try_str(qdict, "id"));
73
+ if (!id) {
74
+ error_setg(errp, QERR_MISSING_PARAMETER, "id");
75
+ return;
76
+ }
77
+ qdict_del(qdict, "id");
78
+
79
+ v = qobject_input_visitor_new(QOBJECT(qdict));
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)
86
{
87
diff --git a/qom/qom-qmp-cmds.c b/qom/qom-qmp-cmds.c
88
index XXXXXXX..XXXXXXX 100644
89
--- a/qom/qom-qmp-cmds.c
90
+++ b/qom/qom-qmp-cmds.c
91
@@ -XXX,XX +XXX,XX @@
92
#include "qapi/qapi-commands-qom.h"
93
#include "qapi/qmp/qdict.h"
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);
126
}
127
128
- v = qobject_input_visitor_new(QOBJECT(qdict));
129
- obj = user_creatable_add_type(type, id, qdict, v, errp);
130
- visit_free(v);
131
- object_unref(obj);
132
+ user_creatable_add_dict(qdict, errp);
133
}
134
135
void qmp_object_del(const char *id, Error **errp)
33
--
136
--
34
2.13.6
137
2.25.3
35
138
36
139
diff view generated by jsdifflib
1
From: KONRAD Frederic <frederic.konrad@adacore.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
Since 42a3e1ab367cdf38cce093de24eb406b99a4ef96 qemu asserts when using the
5
qmp_object_add(), however, uses the normal QObject input visitor, which
4
vvfat driver:
6
expects a QDict where all properties already have the QType that matches
7
the data type required by the QOM object type.
5
8
6
git clone git://qemu.org/qemu.git
9
Change the --object implementation in qemu-storage-daemon so that it
7
cd qemu
10
doesn't call qmp_object_add(), but calls user_creatable_add_dict()
8
./configure --target-list=ppc-softmmu --enable-debug
11
directly instead and pass it a new keyval boolean that decides which
9
make -j8
12
visitor must be used.
10
mkdir foo
11
touch foo/hello
12
./ppc-softmmu/qemu-system-ppc -M prep --nographic --monitor null \
13
-hda fat:rw:./foo
14
13
15
"Ctrl-C"
14
Reported-by: Coiby Xu <coiby.xu@gmail.com>
16
17
qemu-system-ppc: block.c:3368: bdrv_close_all: Assertion \
18
`((&all_bdrv_states)->tqh_first == ((void *)0))' failed.
19
20
This is because we reference bs twice in qcow_co_create(..) one time in
21
bdrv_open_blockdev_ref(..) and in blk_insert_bs(..) but we unref it only once
22
in blk_unref which leads to the reference leak.
23
24
Note that I didn't tested much QCOW after this change as I don't use it much.
25
26
Signed-off-by: KONRAD Frederic <frederic.konrad@adacore.com>
27
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
28
---
16
---
29
block/qcow.c | 1 +
17
include/qom/object_interfaces.h | 6 +++++-
30
1 file changed, 1 insertion(+)
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(-)
31
22
32
diff --git a/block/qcow.c b/block/qcow.c
23
diff --git a/include/qom/object_interfaces.h b/include/qom/object_interfaces.h
33
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
34
--- a/block/qcow.c
25
--- a/include/qom/object_interfaces.h
35
+++ b/block/qcow.c
26
+++ b/include/qom/object_interfaces.h
36
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow_co_create(BlockdevCreateOptions *opts,
27
@@ -XXX,XX +XXX,XX @@ Object *user_creatable_add_type(const char *type, const char *id,
37
ret = 0;
28
/**
38
exit:
29
* user_creatable_add_dict:
39
blk_unref(qcow_blk);
30
* @qdict: the object definition
40
+ bdrv_unref(bs);
31
+ * @keyval: if true, use a keyval visitor for processing @qdict (i.e.
41
qcrypto_block_free(crypto);
32
+ * assume that all @qdict values are strings); otherwise, use
42
return ret;
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;
43
}
76
}
77
78
-void user_creatable_add_dict(QDict *qdict, Error **errp)
79
+void user_creatable_add_dict(QDict *qdict, bool keyval, Error **errp)
80
{
81
Visitor *v;
82
Object *obj;
83
@@ -XXX,XX +XXX,XX @@ void user_creatable_add_dict(QDict *qdict, Error **errp)
84
}
85
qdict_del(qdict, "id");
86
87
- v = qobject_input_visitor_new(QOBJECT(qdict));
88
+ if (keyval) {
89
+ v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
90
+ } else {
91
+ v = qobject_input_visitor_new(QOBJECT(qdict));
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)
44
--
109
--
45
2.13.6
110
2.25.3
46
111
47
112
diff view generated by jsdifflib