1
The following changes since commit 609ef9f451759151d0bfe7c3843410ab94d68f18:
1
The following changes since commit 16aaacb307ed607b9780c12702c44f0fe52edc7e:
2
2
3
Merge remote-tracking branch 'remotes/berrange/tags/qio-next-pull-request' into staging (2018-06-28 17:53:31 +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 583c99d39368526dfb57a715b04a6ceea27dbe1e:
9
for you to fetch changes up to eaae29ef89d498d0eac553c77b554f310a47f809:
10
10
11
block: Remove unused sector-based vectored I/O (2018-06-29 14:20:56 +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
- Make truncate operations asynchronous (so that preallocation in
16
- Fix resize (extending) of short overlays
17
blockdev-create doesn't block the main loop any more)
17
- nvme: introduce PMR support from NVMe 1.4 spec
18
- usb-storage: Add rerror/werror properties
18
- qemu-storage-daemon: Fix non-string --object properties
19
- nvme: Add num_queues property
20
- qemu-img convert: Copy offloading fixes (including data corruption fix)
21
- qcow2: Fix cluster leak on temporary write error
22
- Use byte-based functions instead of bdrv_co_readv/writev()
23
- Various small fixes and cleanups
24
19
25
----------------------------------------------------------------
20
----------------------------------------------------------------
26
Eric Blake (8):
21
Alberto Garcia (1):
27
parallels: Switch to byte-based calls
22
qcow2: Add incompatibility note between backing files and raw external data files
28
qcow: Switch get_cluster_offset to be byte-based
29
qcow: Switch qcow_co_readv to byte-based calls
30
qcow: Switch qcow_co_writev to byte-based calls
31
qcow: Switch to a byte-based driver
32
replication: Switch to byte-based calls
33
vhdx: Switch to byte-based calls
34
block: Remove unused sector-based vectored I/O
35
23
36
Fam Zheng (5):
24
Andrzej Jakowski (1):
37
qcow2: Remove dead check on !ret
25
nvme: introduce PMR support from NVMe 1.4 spec
38
block: Move request tracking to children in copy offloading
39
qcow2: Fix src_offset in copy offloading
40
iscsi: Don't blindly use designator length in response for memcpy
41
file-posix: Fix EINTR handling
42
26
43
Kevin Wolf (12):
27
Kevin Wolf (12):
44
qapi/job: The next release will be 3.0
28
block: Add flags to BlockDriver.bdrv_co_truncate()
45
usb-storage: Add rerror/werror properties
29
block: Add flags to bdrv(_co)_truncate()
46
qcow2: Fix qcow2_truncate() error return value
30
block-backend: Add flags to blk_truncate()
47
block: Convert .bdrv_truncate callback to coroutine_fn
31
qcow2: Support BDRV_REQ_ZERO_WRITE for truncate
48
qcow2: Remove coroutine trampoline for preallocate_co()
32
raw-format: Support BDRV_REQ_ZERO_WRITE for truncate
49
block: Move bdrv_truncate() implementation to io.c
33
file-posix: Support BDRV_REQ_ZERO_WRITE for truncate
50
block: Use tracked request for truncate
34
block: truncate: Don't make backing file data visible
51
file-posix: Make .bdrv_co_truncate asynchronous
35
iotests: Filter testfiles out in filter_img_info()
52
qemu-iotests: Update 026.out.nocache reference output
36
iotests: Test committing to short backing file
53
qcow2: Free allocated clusters on write error
37
qcow2: Forward ZERO_WRITE flag for full preallocation
54
qemu-iotests: Test qcow2 not leaking clusters on write error
38
qom: Factor out user_creatable_add_dict()
55
file-posix: Implement co versions of discard/flush
39
qemu-storage-daemon: Fix non-string --object properties
56
40
57
Markus Armbruster (3):
41
Paolo Bonzini (1):
58
block-qdict: Pacify Coverity after commit f1b34a248e9
42
qemu-iotests: allow qcow2 external discarded clusters to contain stale data
59
block/crypto: Pacify Coverity after commit f853465aacb
60
block/crypto: Simplify block_crypto_{open,create}_opts_init()
61
43
62
Weiping Zhang (1):
44
docs/interop/qcow2.txt | 3 +
63
hw/block/nvme: add optional parameter num_queues for nvme device
45
hw/block/nvme.h | 2 +
46
include/block/block.h | 5 +-
47
include/block/block_int.h | 10 +-
48
include/block/nvme.h | 172 ++++++++++++++++++++++++++
49
include/qom/object_interfaces.h | 16 +++
50
include/sysemu/block-backend.h | 2 +-
51
block.c | 3 +-
52
block/block-backend.c | 4 +-
53
block/commit.c | 4 +-
54
block/crypto.c | 7 +-
55
block/file-posix.c | 6 +-
56
block/file-win32.c | 2 +-
57
block/gluster.c | 1 +
58
block/io.c | 43 ++++++-
59
block/iscsi.c | 2 +-
60
block/mirror.c | 2 +-
61
block/nfs.c | 3 +-
62
block/parallels.c | 6 +-
63
block/qcow.c | 4 +-
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
64
96
65
qapi/job.json | 18 +-
66
block/crypto.h | 8 +-
67
block/qcow2.h | 1 +
68
include/block/block.h | 8 +-
69
include/block/block_int.h | 7 +-
70
include/block/raw-aio.h | 4 +-
71
include/hw/scsi/scsi.h | 2 +
72
block.c | 64 +------
73
block/copy-on-read.c | 8 +-
74
block/crypto.c | 112 +++--------
75
block/file-posix.c | 367 +++++++++++++++++++------------------
76
block/file-win32.c | 6 +-
77
block/gluster.c | 14 +-
78
block/io.c | 219 +++++++++++++++-------
79
block/iscsi.c | 10 +-
80
block/nfs.c | 7 +-
81
block/parallels.c | 16 +-
82
block/qcow.c | 135 +++++++-------
83
block/qcow2-cluster.c | 11 ++
84
block/qcow2.c | 140 ++++++--------
85
block/qed.c | 8 +-
86
block/raw-format.c | 8 +-
87
block/rbd.c | 8 +-
88
block/replication.c | 14 +-
89
block/sheepdog.c | 12 +-
90
block/ssh.c | 6 +-
91
block/vhdx.c | 12 +-
92
hw/block/nvme.c | 5 +-
93
hw/scsi/scsi-bus.c | 11 +-
94
hw/usb/dev-storage.c | 2 +
95
qobject/block-qdict.c | 16 +-
96
tests/qemu-iotests/026 | 17 ++
97
tests/qemu-iotests/026.out | 8 +
98
tests/qemu-iotests/026.out.nocache | 14 +-
99
tests/qemu-iotests/063 | 9 +
100
tests/qemu-iotests/063.out | 12 ++
101
36 files changed, 685 insertions(+), 634 deletions(-)
102
97
diff view generated by jsdifflib
Deleted patch
1
From: Markus Armbruster <armbru@redhat.com>
2
1
3
Commit f1b34a248e9 replaced less-than-obvious test in
4
qdict_flatten_qdict() by the obvious one. Sadly, it made something
5
else non-obvious: the fact that @new_key passed to qdict_put_obj()
6
can't be null, because that depends on the function's precondition
7
(target == qdict) == !prefix.
8
9
Tweak the function some more to help Coverity and human readers alike.
10
11
Fixes: CID 1393620
12
Signed-off-by: Markus Armbruster <armbru@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
---
15
qobject/block-qdict.c | 16 ++++++++--------
16
1 file changed, 8 insertions(+), 8 deletions(-)
17
18
diff --git a/qobject/block-qdict.c b/qobject/block-qdict.c
19
index XXXXXXX..XXXXXXX 100644
20
--- a/qobject/block-qdict.c
21
+++ b/qobject/block-qdict.c
22
@@ -XXX,XX +XXX,XX @@ static void qdict_flatten_qdict(QDict *qdict, QDict *target, const char *prefix)
23
const QDictEntry *entry, *next;
24
QDict *dict_val;
25
QList *list_val;
26
- char *new_key;
27
+ char *key, *new_key;
28
29
entry = qdict_first(qdict);
30
31
@@ -XXX,XX +XXX,XX @@ static void qdict_flatten_qdict(QDict *qdict, QDict *target, const char *prefix)
32
value = qdict_entry_value(entry);
33
dict_val = qobject_to(QDict, value);
34
list_val = qobject_to(QList, value);
35
- new_key = NULL;
36
37
if (prefix) {
38
- new_key = g_strdup_printf("%s.%s", prefix, entry->key);
39
+ key = new_key = g_strdup_printf("%s.%s", prefix, entry->key);
40
+ } else {
41
+ key = entry->key;
42
+ new_key = NULL;
43
}
44
45
/*
46
@@ -XXX,XX +XXX,XX @@ static void qdict_flatten_qdict(QDict *qdict, QDict *target, const char *prefix)
47
* well advised not to modify them altogether.)
48
*/
49
if (dict_val && qdict_size(dict_val)) {
50
- qdict_flatten_qdict(dict_val, target,
51
- new_key ? new_key : entry->key);
52
+ qdict_flatten_qdict(dict_val, target, key);
53
if (target == qdict) {
54
qdict_del(qdict, entry->key);
55
}
56
} else if (list_val && !qlist_empty(list_val)) {
57
- qdict_flatten_qlist(list_val, target,
58
- new_key ? new_key : entry->key);
59
+ qdict_flatten_qlist(list_val, target, key);
60
if (target == qdict) {
61
qdict_del(qdict, entry->key);
62
}
63
} else if (target != qdict) {
64
- qdict_put_obj(target, new_key, qobject_ref(value));
65
+ qdict_put_obj(target, key, qobject_ref(value));
66
}
67
68
g_free(new_key);
69
--
70
2.13.6
71
72
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
1
From: Alberto Garcia <berto@igalia.com>
2
2
3
We are gradually moving away from sector-based interfaces, towards
3
Backing files and raw external data files are mutually exclusive.
4
byte-based. Make the change for the last few sector-based calls
4
The documentation of the raw external data bit (in autoclear_features)
5
into the block layer from the vhdx driver.
5
already indicates that, but we should also mention it on the other
6
side.
6
7
7
Ideally, the vhdx driver should switch to doing everything
8
Suggested-by: Eric Blake <eblake@redhat.com>
8
byte-based, but that's a more invasive change that requires a
9
Signed-off-by: Alberto Garcia <berto@igalia.com>
9
bit more auditing.
10
Message-Id: <20200410121816.8334-1-berto@igalia.com>
10
11
Reviewed-by: Eric Blake <eblake@redhat.com>
11
Signed-off-by: Eric Blake <eblake@redhat.com>
12
Reviewed-by: Jeff Cody <jcody@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
---
13
---
15
block/vhdx.c | 12 ++++++------
14
docs/interop/qcow2.txt | 3 +++
16
1 file changed, 6 insertions(+), 6 deletions(-)
15
1 file changed, 3 insertions(+)
17
16
18
diff --git a/block/vhdx.c b/block/vhdx.c
17
diff --git a/docs/interop/qcow2.txt b/docs/interop/qcow2.txt
19
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
20
--- a/block/vhdx.c
19
--- a/docs/interop/qcow2.txt
21
+++ b/block/vhdx.c
20
+++ b/docs/interop/qcow2.txt
22
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int vhdx_co_readv(BlockDriverState *bs, int64_t sector_num,
21
@@ -XXX,XX +XXX,XX @@ The first cluster of a qcow2 image contains the file header:
23
break;
22
is stored (NB: The string is not null terminated). 0 if the
24
case PAYLOAD_BLOCK_FULLY_PRESENT:
23
image doesn't have a backing file.
25
qemu_co_mutex_unlock(&s->lock);
24
26
- ret = bdrv_co_readv(bs->file,
25
+ Note: backing files are incompatible with raw external data
27
- sinfo.file_offset >> BDRV_SECTOR_BITS,
26
+ files (auto-clear feature bit 1).
28
- sinfo.sectors_avail, &hd_qiov);
27
+
29
+ ret = bdrv_co_preadv(bs->file, sinfo.file_offset,
28
16 - 19: backing_file_size
30
+ sinfo.sectors_avail * BDRV_SECTOR_SIZE,
29
Length of the backing file name in bytes. Must not be
31
+ &hd_qiov, 0);
30
longer than 1023 bytes. Undefined if the image doesn't have
32
qemu_co_mutex_lock(&s->lock);
33
if (ret < 0) {
34
goto exit;
35
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int vhdx_co_writev(BlockDriverState *bs, int64_t sector_num,
36
}
37
/* block exists, so we can just overwrite it */
38
qemu_co_mutex_unlock(&s->lock);
39
- ret = bdrv_co_writev(bs->file,
40
- sinfo.file_offset >> BDRV_SECTOR_BITS,
41
- sectors_to_write, &hd_qiov);
42
+ ret = bdrv_co_pwritev(bs->file, sinfo.file_offset,
43
+ sectors_to_write * BDRV_SECTOR_SIZE,
44
+ &hd_qiov, 0);
45
qemu_co_mutex_lock(&s->lock);
46
if (ret < 0) {
47
goto error_bat_restore;
48
--
31
--
49
2.13.6
32
2.25.3
50
33
51
34
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
2
3
We are gradually moving away from sector-based interfaces, towards
3
Test 244 checks the expected behavior of qcow2 external data files
4
byte-based. Make the change for the last few sector-based calls
4
with respect to zero and discarded clusters. Filesystems however
5
into the block layer from the replication driver.
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.
6
9
7
Ideally, the replication driver should switch to doing everything
10
This fixes docker tests on RHEL8.
8
byte-based, but that's a more invasive change that requires a
9
bit more auditing.
10
11
11
Signed-off-by: Eric Blake <eblake@redhat.com>
12
Cc: Kevin Wolf <kwolf@redhat.com>
12
Reviewed-by: Jeff Cody <jcody@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>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
16
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
---
17
---
15
block/replication.c | 14 ++++++++------
18
tests/qemu-iotests/244 | 10 ++++++++--
16
1 file changed, 8 insertions(+), 6 deletions(-)
19
tests/qemu-iotests/244.out | 9 ++++++---
20
2 files changed, 14 insertions(+), 5 deletions(-)
17
21
18
diff --git a/block/replication.c b/block/replication.c
22
diff --git a/tests/qemu-iotests/244 b/tests/qemu-iotests/244
23
index XXXXXXX..XXXXXXX 100755
24
--- a/tests/qemu-iotests/244
25
+++ b/tests/qemu-iotests/244
26
@@ -XXX,XX +XXX,XX @@ $QEMU_IO -c 'read -P 0 0 1M' \
27
echo
28
$QEMU_IO -c 'read -P 0 0 1M' \
29
-c 'read -P 0x11 1M 1M' \
30
- -c 'read -P 0 2M 2M' \
31
-c 'read -P 0x11 4M 1M' \
32
-c 'read -P 0 5M 1M' \
33
-f raw "$TEST_IMG.data" |
34
@@ -XXX,XX +XXX,XX @@ $QEMU_IO -c 'read -P 0 0 1M' \
35
-f $IMGFMT "$TEST_IMG" |
36
_filter_qemu_io
37
38
+# Discarded clusters are only marked as such in the qcow2 metadata, but
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
19
index XXXXXXX..XXXXXXX 100644
52
index XXXXXXX..XXXXXXX 100644
20
--- a/block/replication.c
53
--- a/tests/qemu-iotests/244.out
21
+++ b/block/replication.c
54
+++ b/tests/qemu-iotests/244.out
22
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int replication_co_readv(BlockDriverState *bs,
55
@@ -XXX,XX +XXX,XX @@ read 1048576/1048576 bytes at offset 0
23
backup_cow_request_begin(&req, child->bs->job,
56
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
24
sector_num * BDRV_SECTOR_SIZE,
57
read 1048576/1048576 bytes at offset 1048576
25
remaining_bytes);
58
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
26
- ret = bdrv_co_readv(bs->file, sector_num, remaining_sectors,
59
-read 2097152/2097152 bytes at offset 2097152
27
- qiov);
60
-2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
28
+ ret = bdrv_co_preadv(bs->file, sector_num * BDRV_SECTOR_SIZE,
61
read 1048576/1048576 bytes at offset 4194304
29
+ remaining_bytes, qiov, 0);
62
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
30
backup_cow_request_end(&req);
63
read 1048576/1048576 bytes at offset 5242880
31
goto out;
64
@@ -XXX,XX +XXX,XX @@ read 1048576/1048576 bytes at offset 1048576
32
}
65
read 4194304/4194304 bytes at offset 2097152
33
66
4 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
34
- ret = bdrv_co_readv(bs->file, sector_num, remaining_sectors, qiov);
67
35
+ ret = bdrv_co_preadv(bs->file, sector_num * BDRV_SECTOR_SIZE,
68
-Images are identical.
36
+ remaining_sectors * BDRV_SECTOR_SIZE, qiov, 0);
69
+read 1048576/1048576 bytes at offset 0
37
out:
70
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
38
return replication_return_value(s, ret);
71
+read 1048576/1048576 bytes at offset 1048576
39
}
72
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
40
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int replication_co_writev(BlockDriverState *bs,
73
+read 3145728/3145728 bytes at offset 3145728
41
}
74
+3 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
42
75
qcow2 file size after I/O: 327680
43
if (ret == 0) {
76
44
- ret = bdrv_co_writev(top, sector_num,
77
=== bdrv_co_block_status test for file and offset=0 ===
45
- remaining_sectors, qiov);
46
+ ret = bdrv_co_pwritev(top, sector_num * BDRV_SECTOR_SIZE,
47
+ remaining_sectors * BDRV_SECTOR_SIZE, qiov, 0);
48
return replication_return_value(s, ret);
49
}
50
51
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int replication_co_writev(BlockDriverState *bs,
52
qemu_iovec_concat(&hd_qiov, qiov, bytes_done, count);
53
54
target = ret ? top : base;
55
- ret = bdrv_co_writev(target, sector_num, n, &hd_qiov);
56
+ ret = bdrv_co_pwritev(target, sector_num * BDRV_SECTOR_SIZE,
57
+ n * BDRV_SECTOR_SIZE, &hd_qiov, 0);
58
if (ret < 0) {
59
goto out1;
60
}
61
--
78
--
62
2.13.6
79
2.25.3
63
80
64
81
diff view generated by jsdifflib
1
bdrv_truncate() is an operation that can block (even for a quite long
1
This adds a new BdrvRequestFlags parameter to the .bdrv_co_truncate()
2
time, depending on the PreallocMode) in I/O paths that shouldn't block.
2
driver callbacks, and a supported_truncate_flags field in
3
Convert it to a coroutine_fn so that we have the infrastructure for
3
BlockDriverState that allows drivers to advertise support for request
4
drivers to make their .bdrv_co_truncate implementation asynchronous.
4
flags in the context of truncate.
5
5
6
This change could potentially introduce new race conditions because
6
For now, we always pass 0 and no drivers declare support for any flag.
7
bdrv_truncate() isn't necessarily executed atomically any more. Whether
8
this is a problem needs to be evaluated for each block driver that
9
supports truncate:
10
11
* file-posix/win32, gluster, iscsi, nfs, rbd, ssh, sheepdog: The
12
protocol drivers are trivially safe because they don't actually yield
13
yet, so there is no change in behaviour.
14
15
* copy-on-read, crypto, raw-format: Essentially just filter drivers that
16
pass the request to a child node, no problem.
17
18
* qcow2: The implementation modifies metadata, so it needs to hold
19
s->lock to be safe with concurrent I/O requests. In order to avoid
20
double locking, this requires pulling the locking out into
21
preallocate_co() and using qcow2_write_caches() instead of
22
bdrv_flush().
23
24
* qed: Does a single header update, this is fine without locking.
25
7
26
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
27
Reviewed-by: Stefan Hajnoczi <stefanha@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>
28
---
14
---
29
include/block/block.h | 4 +++
15
include/block/block_int.h | 10 +++++++++-
30
include/block/block_int.h | 4 +--
16
block/crypto.c | 3 ++-
31
block.c | 63 +++++++++++++++++++++++++++++++++++-----
17
block/file-posix.c | 2 +-
32
block/copy-on-read.c | 8 ++---
18
block/file-win32.c | 2 +-
33
block/crypto.c | 9 +++---
19
block/gluster.c | 1 +
34
block/file-posix.c | 12 ++++----
20
block/io.c | 8 +++++++-
35
block/file-win32.c | 6 ++--
21
block/iscsi.c | 2 +-
36
block/gluster.c | 14 +++++----
22
block/nfs.c | 3 ++-
37
block/iscsi.c | 8 ++---
23
block/qcow2.c | 2 +-
38
block/nfs.c | 7 +++--
24
block/qed.c | 1 +
39
block/qcow2.c | 74 ++++++++++++++++++++++++++++-------------------
25
block/raw-format.c | 2 +-
40
block/qed.c | 8 +++--
26
block/rbd.c | 1 +
41
block/raw-format.c | 8 ++---
27
block/sheepdog.c | 4 ++--
42
block/rbd.c | 8 +++--
28
block/ssh.c | 2 +-
43
block/sheepdog.c | 12 ++++----
29
tests/test-block-iothread.c | 3 ++-
44
block/ssh.c | 6 ++--
30
15 files changed, 33 insertions(+), 13 deletions(-)
45
16 files changed, 162 insertions(+), 89 deletions(-)
31
46
47
diff --git a/include/block/block.h b/include/block/block.h
48
index XXXXXXX..XXXXXXX 100644
49
--- a/include/block/block.h
50
+++ b/include/block/block.h
51
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_pwrite_zeroes(BdrvChild *child, int64_t offset,
52
BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs,
53
const char *backing_file);
54
void bdrv_refresh_filename(BlockDriverState *bs);
55
+
56
+int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset,
57
+ PreallocMode prealloc, Error **errp);
58
int bdrv_truncate(BdrvChild *child, int64_t offset, PreallocMode prealloc,
59
Error **errp);
60
+
61
int64_t bdrv_nb_sectors(BlockDriverState *bs);
62
int64_t bdrv_getlength(BlockDriverState *bs);
63
int64_t bdrv_get_allocated_file_size(BlockDriverState *bs);
64
diff --git a/include/block/block_int.h b/include/block/block_int.h
32
diff --git a/include/block/block_int.h b/include/block/block_int.h
65
index XXXXXXX..XXXXXXX 100644
33
index XXXXXXX..XXXXXXX 100644
66
--- a/include/block/block_int.h
34
--- a/include/block/block_int.h
67
+++ b/include/block/block_int.h
35
+++ b/include/block/block_int.h
68
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
36
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
69
* bdrv_parse_filename.
70
*/
37
*/
71
const char *protocol_name;
38
int coroutine_fn (*bdrv_co_truncate)(BlockDriverState *bs, int64_t offset,
72
- int (*bdrv_truncate)(BlockDriverState *bs, int64_t offset,
39
bool exact, PreallocMode prealloc,
73
- PreallocMode prealloc, Error **errp);
40
- Error **errp);
74
+ int coroutine_fn (*bdrv_co_truncate)(BlockDriverState *bs, int64_t offset,
41
+ BdrvRequestFlags flags, Error **errp);
75
+ PreallocMode prealloc, Error **errp);
76
42
77
int64_t (*bdrv_getlength)(BlockDriverState *bs);
43
int64_t (*bdrv_getlength)(BlockDriverState *bs);
78
bool has_variable_length;
44
bool has_variable_length;
79
diff --git a/block.c b/block.c
45
@@ -XXX,XX +XXX,XX @@ struct BlockDriverState {
80
index XXXXXXX..XXXXXXX 100644
46
/* Flags honored during pwrite_zeroes (so far: BDRV_REQ_FUA,
81
--- a/block.c
47
* BDRV_REQ_MAY_UNMAP, BDRV_REQ_WRITE_UNCHANGED) */
82
+++ b/block.c
48
unsigned int supported_zero_flags;
83
@@ -XXX,XX +XXX,XX @@ exit:
49
+ /*
84
/**
50
+ * Flags honoured during truncate (so far: BDRV_REQ_ZERO_WRITE).
85
* Truncate file to 'offset' bytes (needed only for file protocols)
51
+ *
86
*/
52
+ * If BDRV_REQ_ZERO_WRITE is given, the truncate operation must make sure
87
-int bdrv_truncate(BdrvChild *child, int64_t offset, PreallocMode prealloc,
53
+ * that any added space reads as all zeros. If this can't be guaranteed,
88
- Error **errp)
54
+ * the operation must fail.
89
+int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset,
55
+ */
90
+ PreallocMode prealloc, Error **errp)
56
+ unsigned int supported_truncate_flags;
91
{
57
92
BlockDriverState *bs = child->bs;
58
/* the following member gives a name to every node on the bs graph. */
93
BlockDriver *drv = bs->drv;
59
char node_name[32];
94
@@ -XXX,XX +XXX,XX @@ int bdrv_truncate(BdrvChild *child, int64_t offset, PreallocMode prealloc,
95
return -EINVAL;
96
}
97
98
- if (!drv->bdrv_truncate) {
99
+ bdrv_inc_in_flight(bs);
100
+
101
+ if (!drv->bdrv_co_truncate) {
102
if (bs->file && drv->is_filter) {
103
- return bdrv_truncate(bs->file, offset, prealloc, errp);
104
+ ret = bdrv_co_truncate(bs->file, offset, prealloc, errp);
105
+ goto out;
106
}
107
error_setg(errp, "Image format driver does not support resize");
108
- return -ENOTSUP;
109
+ ret = -ENOTSUP;
110
+ goto out;
111
}
112
if (bs->read_only) {
113
error_setg(errp, "Image is read-only");
114
- return -EACCES;
115
+ ret = -EACCES;
116
+ goto out;
117
}
118
119
assert(!(bs->open_flags & BDRV_O_INACTIVE));
120
121
- ret = drv->bdrv_truncate(bs, offset, prealloc, errp);
122
+ ret = drv->bdrv_co_truncate(bs, offset, prealloc, errp);
123
if (ret < 0) {
124
- return ret;
125
+ goto out;
126
}
127
ret = refresh_total_sectors(bs, offset >> BDRV_SECTOR_BITS);
128
if (ret < 0) {
129
@@ -XXX,XX +XXX,XX @@ int bdrv_truncate(BdrvChild *child, int64_t offset, PreallocMode prealloc,
130
bdrv_dirty_bitmap_truncate(bs, offset);
131
bdrv_parent_cb_resize(bs);
132
atomic_inc(&bs->write_gen);
133
+
134
+out:
135
+ bdrv_dec_in_flight(bs);
136
return ret;
137
}
138
139
+typedef struct TruncateCo {
140
+ BdrvChild *child;
141
+ int64_t offset;
142
+ PreallocMode prealloc;
143
+ Error **errp;
144
+ int ret;
145
+} TruncateCo;
146
+
147
+static void coroutine_fn bdrv_truncate_co_entry(void *opaque)
148
+{
149
+ TruncateCo *tco = opaque;
150
+ tco->ret = bdrv_co_truncate(tco->child, tco->offset, tco->prealloc,
151
+ tco->errp);
152
+}
153
+
154
+int bdrv_truncate(BdrvChild *child, int64_t offset, PreallocMode prealloc,
155
+ Error **errp)
156
+{
157
+ Coroutine *co;
158
+ TruncateCo tco = {
159
+ .child = child,
160
+ .offset = offset,
161
+ .prealloc = prealloc,
162
+ .errp = errp,
163
+ .ret = NOT_DONE,
164
+ };
165
+
166
+ if (qemu_in_coroutine()) {
167
+ /* Fast-path if already in coroutine context */
168
+ bdrv_truncate_co_entry(&tco);
169
+ } else {
170
+ co = qemu_coroutine_create(bdrv_truncate_co_entry, &tco);
171
+ qemu_coroutine_enter(co);
172
+ BDRV_POLL_WHILE(child->bs, tco.ret == NOT_DONE);
173
+ }
174
+
175
+ return tco.ret;
176
+}
177
+
178
/**
179
* Length of a allocated file in bytes. Sparse files are counted by actual
180
* allocated space. Return < 0 if error or unknown.
181
diff --git a/block/copy-on-read.c b/block/copy-on-read.c
182
index XXXXXXX..XXXXXXX 100644
183
--- a/block/copy-on-read.c
184
+++ b/block/copy-on-read.c
185
@@ -XXX,XX +XXX,XX @@ static int64_t cor_getlength(BlockDriverState *bs)
186
}
187
188
189
-static int cor_truncate(BlockDriverState *bs, int64_t offset,
190
- PreallocMode prealloc, Error **errp)
191
+static int coroutine_fn cor_co_truncate(BlockDriverState *bs, int64_t offset,
192
+ PreallocMode prealloc, Error **errp)
193
{
194
- return bdrv_truncate(bs->file, offset, prealloc, errp);
195
+ return bdrv_co_truncate(bs->file, offset, prealloc, errp);
196
}
197
198
199
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_copy_on_read = {
200
.bdrv_child_perm = cor_child_perm,
201
202
.bdrv_getlength = cor_getlength,
203
- .bdrv_truncate = cor_truncate,
204
+ .bdrv_co_truncate = cor_co_truncate,
205
206
.bdrv_co_preadv = cor_co_preadv,
207
.bdrv_co_pwritev = cor_co_pwritev,
208
diff --git a/block/crypto.c b/block/crypto.c
60
diff --git a/block/crypto.c b/block/crypto.c
209
index XXXXXXX..XXXXXXX 100644
61
index XXXXXXX..XXXXXXX 100644
210
--- a/block/crypto.c
62
--- a/block/crypto.c
211
+++ b/block/crypto.c
63
+++ b/block/crypto.c
212
@@ -XXX,XX +XXX,XX @@ static int block_crypto_co_create_generic(BlockDriverState *bs,
64
@@ -XXX,XX +XXX,XX @@ static int block_crypto_co_create_generic(BlockDriverState *bs,
213
return ret;
65
214
}
66
static int coroutine_fn
215
67
block_crypto_co_truncate(BlockDriverState *bs, int64_t offset, bool exact,
216
-static int block_crypto_truncate(BlockDriverState *bs, int64_t offset,
68
- PreallocMode prealloc, Error **errp)
217
- PreallocMode prealloc, Error **errp)
69
+ PreallocMode prealloc, BdrvRequestFlags flags,
218
+static int coroutine_fn
70
+ Error **errp)
219
+block_crypto_co_truncate(BlockDriverState *bs, int64_t offset,
220
+ PreallocMode prealloc, Error **errp)
221
{
71
{
222
BlockCrypto *crypto = bs->opaque;
72
BlockCrypto *crypto = bs->opaque;
223
uint64_t payload_offset =
73
uint64_t payload_offset =
224
@@ -XXX,XX +XXX,XX @@ static int block_crypto_truncate(BlockDriverState *bs, int64_t offset,
225
226
offset += payload_offset;
227
228
- return bdrv_truncate(bs->file, offset, prealloc, errp);
229
+ return bdrv_co_truncate(bs->file, offset, prealloc, errp);
230
}
231
232
static void block_crypto_close(BlockDriverState *bs)
233
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_crypto_luks = {
234
.bdrv_child_perm = bdrv_format_default_perms,
235
.bdrv_co_create = block_crypto_co_create_luks,
236
.bdrv_co_create_opts = block_crypto_co_create_opts_luks,
237
- .bdrv_truncate = block_crypto_truncate,
238
+ .bdrv_co_truncate = block_crypto_co_truncate,
239
.create_opts = &block_crypto_create_opts_luks,
240
241
.bdrv_reopen_prepare = block_crypto_reopen_prepare,
242
diff --git a/block/file-posix.c b/block/file-posix.c
74
diff --git a/block/file-posix.c b/block/file-posix.c
243
index XXXXXXX..XXXXXXX 100644
75
index XXXXXXX..XXXXXXX 100644
244
--- a/block/file-posix.c
76
--- a/block/file-posix.c
245
+++ b/block/file-posix.c
77
+++ b/block/file-posix.c
246
@@ -XXX,XX +XXX,XX @@ out:
78
@@ -XXX,XX +XXX,XX @@ raw_regular_truncate(BlockDriverState *bs, int fd, int64_t offset,
247
return result;
79
248
}
80
static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset,
249
81
bool exact, PreallocMode prealloc,
250
-static int raw_truncate(BlockDriverState *bs, int64_t offset,
82
- Error **errp)
251
- PreallocMode prealloc, Error **errp)
83
+ BdrvRequestFlags flags, Error **errp)
252
+static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset,
253
+ PreallocMode prealloc, Error **errp)
254
{
84
{
255
BDRVRawState *s = bs->opaque;
85
BDRVRawState *s = bs->opaque;
256
struct stat st;
86
struct stat st;
257
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_file = {
258
.bdrv_io_unplug = raw_aio_unplug,
259
.bdrv_attach_aio_context = raw_aio_attach_aio_context,
260
261
- .bdrv_truncate = raw_truncate,
262
+ .bdrv_co_truncate = raw_co_truncate,
263
.bdrv_getlength = raw_getlength,
264
.bdrv_get_info = raw_get_info,
265
.bdrv_get_allocated_file_size
266
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_host_device = {
267
.bdrv_io_plug = raw_aio_plug,
268
.bdrv_io_unplug = raw_aio_unplug,
269
270
- .bdrv_truncate = raw_truncate,
271
+ .bdrv_co_truncate = raw_co_truncate,
272
.bdrv_getlength    = raw_getlength,
273
.bdrv_get_info = raw_get_info,
274
.bdrv_get_allocated_file_size
275
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_host_cdrom = {
276
.bdrv_io_plug = raw_aio_plug,
277
.bdrv_io_unplug = raw_aio_unplug,
278
279
- .bdrv_truncate = raw_truncate,
280
+ .bdrv_co_truncate = raw_co_truncate,
281
.bdrv_getlength = raw_getlength,
282
.has_variable_length = true,
283
.bdrv_get_allocated_file_size
284
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_host_cdrom = {
285
.bdrv_io_plug = raw_aio_plug,
286
.bdrv_io_unplug = raw_aio_unplug,
287
288
- .bdrv_truncate = raw_truncate,
289
+ .bdrv_co_truncate = raw_co_truncate,
290
.bdrv_getlength = raw_getlength,
291
.has_variable_length = true,
292
.bdrv_get_allocated_file_size
293
diff --git a/block/file-win32.c b/block/file-win32.c
87
diff --git a/block/file-win32.c b/block/file-win32.c
294
index XXXXXXX..XXXXXXX 100644
88
index XXXXXXX..XXXXXXX 100644
295
--- a/block/file-win32.c
89
--- a/block/file-win32.c
296
+++ b/block/file-win32.c
90
+++ b/block/file-win32.c
297
@@ -XXX,XX +XXX,XX @@ static void raw_close(BlockDriverState *bs)
91
@@ -XXX,XX +XXX,XX @@ static void raw_close(BlockDriverState *bs)
298
}
92
299
}
93
static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset,
300
94
bool exact, PreallocMode prealloc,
301
-static int raw_truncate(BlockDriverState *bs, int64_t offset,
95
- Error **errp)
302
- PreallocMode prealloc, Error **errp)
96
+ BdrvRequestFlags flags, Error **errp)
303
+static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset,
304
+ PreallocMode prealloc, Error **errp)
305
{
97
{
306
BDRVRawState *s = bs->opaque;
98
BDRVRawState *s = bs->opaque;
307
LONG low, high;
99
LONG low, high;
308
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_file = {
309
.bdrv_aio_pwritev = raw_aio_pwritev,
310
.bdrv_aio_flush = raw_aio_flush,
311
312
- .bdrv_truncate    = raw_truncate,
313
+ .bdrv_co_truncate = raw_co_truncate,
314
.bdrv_getlength    = raw_getlength,
315
.bdrv_get_allocated_file_size
316
= raw_get_allocated_file_size,
317
diff --git a/block/gluster.c b/block/gluster.c
100
diff --git a/block/gluster.c b/block/gluster.c
318
index XXXXXXX..XXXXXXX 100644
101
index XXXXXXX..XXXXXXX 100644
319
--- a/block/gluster.c
102
--- a/block/gluster.c
320
+++ b/block/gluster.c
103
+++ b/block/gluster.c
321
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qemu_gluster_co_rw(BlockDriverState *bs,
104
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qemu_gluster_co_truncate(BlockDriverState *bs,
322
return acb.ret;
105
int64_t offset,
323
}
106
bool exact,
324
107
PreallocMode prealloc,
325
-static int qemu_gluster_truncate(BlockDriverState *bs, int64_t offset,
108
+ BdrvRequestFlags flags,
326
- PreallocMode prealloc, Error **errp)
109
Error **errp)
327
+static coroutine_fn int qemu_gluster_co_truncate(BlockDriverState *bs,
328
+ int64_t offset,
329
+ PreallocMode prealloc,
330
+ Error **errp)
331
{
110
{
332
BDRVGlusterState *s = bs->opaque;
111
BDRVGlusterState *s = bs->opaque;
333
return qemu_gluster_do_truncate(s->fd, offset, prealloc, errp);
112
diff --git a/block/io.c b/block/io.c
334
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_gluster = {
113
index XXXXXXX..XXXXXXX 100644
335
.bdrv_co_create_opts = qemu_gluster_co_create_opts,
114
--- a/block/io.c
336
.bdrv_getlength = qemu_gluster_getlength,
115
+++ b/block/io.c
337
.bdrv_get_allocated_file_size = qemu_gluster_allocated_file_size,
116
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
338
- .bdrv_truncate = qemu_gluster_truncate,
117
BlockDriverState *bs = child->bs;
339
+ .bdrv_co_truncate = qemu_gluster_co_truncate,
118
BlockDriver *drv = bs->drv;
340
.bdrv_co_readv = qemu_gluster_co_readv,
119
BdrvTrackedRequest req;
341
.bdrv_co_writev = qemu_gluster_co_writev,
120
+ BdrvRequestFlags flags = 0;
342
.bdrv_co_flush_to_disk = qemu_gluster_co_flush_to_disk,
121
int64_t old_size, new_bytes;
343
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_gluster_tcp = {
122
int ret;
344
.bdrv_co_create_opts = qemu_gluster_co_create_opts,
123
345
.bdrv_getlength = qemu_gluster_getlength,
124
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
346
.bdrv_get_allocated_file_size = qemu_gluster_allocated_file_size,
125
}
347
- .bdrv_truncate = qemu_gluster_truncate,
126
348
+ .bdrv_co_truncate = qemu_gluster_co_truncate,
127
if (drv->bdrv_co_truncate) {
349
.bdrv_co_readv = qemu_gluster_co_readv,
128
- ret = drv->bdrv_co_truncate(bs, offset, exact, prealloc, errp);
350
.bdrv_co_writev = qemu_gluster_co_writev,
129
+ if (flags & ~bs->supported_truncate_flags) {
351
.bdrv_co_flush_to_disk = qemu_gluster_co_flush_to_disk,
130
+ error_setg(errp, "Block driver does not support requested flags");
352
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_gluster_unix = {
131
+ ret = -ENOTSUP;
353
.bdrv_co_create_opts = qemu_gluster_co_create_opts,
132
+ goto out;
354
.bdrv_getlength = qemu_gluster_getlength,
133
+ }
355
.bdrv_get_allocated_file_size = qemu_gluster_allocated_file_size,
134
+ ret = drv->bdrv_co_truncate(bs, offset, exact, prealloc, flags, errp);
356
- .bdrv_truncate = qemu_gluster_truncate,
135
} else if (bs->file && drv->is_filter) {
357
+ .bdrv_co_truncate = qemu_gluster_co_truncate,
136
ret = bdrv_co_truncate(bs->file, offset, exact, prealloc, errp);
358
.bdrv_co_readv = qemu_gluster_co_readv,
137
} else {
359
.bdrv_co_writev = qemu_gluster_co_writev,
360
.bdrv_co_flush_to_disk = qemu_gluster_co_flush_to_disk,
361
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_gluster_rdma = {
362
.bdrv_co_create_opts = qemu_gluster_co_create_opts,
363
.bdrv_getlength = qemu_gluster_getlength,
364
.bdrv_get_allocated_file_size = qemu_gluster_allocated_file_size,
365
- .bdrv_truncate = qemu_gluster_truncate,
366
+ .bdrv_co_truncate = qemu_gluster_co_truncate,
367
.bdrv_co_readv = qemu_gluster_co_readv,
368
.bdrv_co_writev = qemu_gluster_co_writev,
369
.bdrv_co_flush_to_disk = qemu_gluster_co_flush_to_disk,
370
diff --git a/block/iscsi.c b/block/iscsi.c
138
diff --git a/block/iscsi.c b/block/iscsi.c
371
index XXXXXXX..XXXXXXX 100644
139
index XXXXXXX..XXXXXXX 100644
372
--- a/block/iscsi.c
140
--- a/block/iscsi.c
373
+++ b/block/iscsi.c
141
+++ b/block/iscsi.c
374
@@ -XXX,XX +XXX,XX @@ static void iscsi_reopen_commit(BDRVReopenState *reopen_state)
142
@@ -XXX,XX +XXX,XX @@ static void iscsi_reopen_commit(BDRVReopenState *reopen_state)
375
}
143
376
}
144
static int coroutine_fn iscsi_co_truncate(BlockDriverState *bs, int64_t offset,
377
145
bool exact, PreallocMode prealloc,
378
-static int iscsi_truncate(BlockDriverState *bs, int64_t offset,
146
- Error **errp)
379
- PreallocMode prealloc, Error **errp)
147
+ BdrvRequestFlags flags, Error **errp)
380
+static int coroutine_fn iscsi_co_truncate(BlockDriverState *bs, int64_t offset,
381
+ PreallocMode prealloc, Error **errp)
382
{
148
{
383
IscsiLun *iscsilun = bs->opaque;
149
IscsiLun *iscsilun = bs->opaque;
384
Error *local_err = NULL;
150
int64_t cur_length;
385
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_iscsi = {
386
387
.bdrv_getlength = iscsi_getlength,
388
.bdrv_get_info = iscsi_get_info,
389
- .bdrv_truncate = iscsi_truncate,
390
+ .bdrv_co_truncate = iscsi_co_truncate,
391
.bdrv_refresh_limits = iscsi_refresh_limits,
392
393
.bdrv_co_block_status = iscsi_co_block_status,
394
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_iser = {
395
396
.bdrv_getlength = iscsi_getlength,
397
.bdrv_get_info = iscsi_get_info,
398
- .bdrv_truncate = iscsi_truncate,
399
+ .bdrv_co_truncate = iscsi_co_truncate,
400
.bdrv_refresh_limits = iscsi_refresh_limits,
401
402
.bdrv_co_block_status = iscsi_co_block_status,
403
diff --git a/block/nfs.c b/block/nfs.c
151
diff --git a/block/nfs.c b/block/nfs.c
404
index XXXXXXX..XXXXXXX 100644
152
index XXXXXXX..XXXXXXX 100644
405
--- a/block/nfs.c
153
--- a/block/nfs.c
406
+++ b/block/nfs.c
154
+++ b/block/nfs.c
407
@@ -XXX,XX +XXX,XX @@ static int64_t nfs_get_allocated_file_size(BlockDriverState *bs)
155
@@ -XXX,XX +XXX,XX @@ static int64_t nfs_get_allocated_file_size(BlockDriverState *bs)
408
return (task.ret < 0 ? task.ret : st.st_blocks * 512);
156
409
}
157
static int coroutine_fn
410
158
nfs_file_co_truncate(BlockDriverState *bs, int64_t offset, bool exact,
411
-static int nfs_file_truncate(BlockDriverState *bs, int64_t offset,
159
- PreallocMode prealloc, Error **errp)
412
- PreallocMode prealloc, Error **errp)
160
+ PreallocMode prealloc, BdrvRequestFlags flags,
413
+static int coroutine_fn
161
+ Error **errp)
414
+nfs_file_co_truncate(BlockDriverState *bs, int64_t offset,
415
+ PreallocMode prealloc, Error **errp)
416
{
162
{
417
NFSClient *client = bs->opaque;
163
NFSClient *client = bs->opaque;
418
int ret;
164
int ret;
419
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_nfs = {
420
421
.bdrv_has_zero_init = nfs_has_zero_init,
422
.bdrv_get_allocated_file_size = nfs_get_allocated_file_size,
423
- .bdrv_truncate = nfs_file_truncate,
424
+ .bdrv_co_truncate = nfs_file_co_truncate,
425
426
.bdrv_file_open = nfs_file_open,
427
.bdrv_close = nfs_file_close,
428
diff --git a/block/qcow2.c b/block/qcow2.c
165
diff --git a/block/qcow2.c b/block/qcow2.c
429
index XXXXXXX..XXXXXXX 100644
166
index XXXXXXX..XXXXXXX 100644
430
--- a/block/qcow2.c
167
--- a/block/qcow2.c
431
+++ b/block/qcow2.c
168
+++ b/block/qcow2.c
432
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn preallocate_co(void *opaque)
433
BlockDriverState *bs = params->bs;
434
uint64_t offset = params->offset;
435
uint64_t new_length = params->new_length;
436
- BDRVQcow2State *s = bs->opaque;
437
uint64_t bytes;
438
uint64_t host_offset = 0;
439
unsigned int cur_bytes;
440
int ret;
441
QCowL2Meta *meta;
442
443
- qemu_co_mutex_lock(&s->lock);
444
-
445
assert(offset <= new_length);
446
bytes = new_length - offset;
447
448
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn preallocate_co(void *opaque)
449
ret = 0;
450
451
done:
452
- qemu_co_mutex_unlock(&s->lock);
453
params->ret = ret;
454
}
455
456
@@ -XXX,XX +XXX,XX @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp)
457
458
/* And if we're supposed to preallocate metadata, do that now */
459
if (qcow2_opts->preallocation != PREALLOC_MODE_OFF) {
460
+ BDRVQcow2State *s = blk_bs(blk)->opaque;
461
+ qemu_co_mutex_lock(&s->lock);
462
ret = preallocate(blk_bs(blk), 0, qcow2_opts->size);
463
+ qemu_co_mutex_unlock(&s->lock);
464
+
465
if (ret < 0) {
466
error_setg_errno(errp, -ret, "Could not preallocate metadata");
467
goto out;
468
@@ -XXX,XX +XXX,XX @@ fail:
169
@@ -XXX,XX +XXX,XX @@ fail:
469
return ret;
170
470
}
171
static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
471
172
bool exact, PreallocMode prealloc,
472
-static int qcow2_truncate(BlockDriverState *bs, int64_t offset,
173
- Error **errp)
473
- PreallocMode prealloc, Error **errp)
174
+ BdrvRequestFlags flags, Error **errp)
474
+static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
475
+ PreallocMode prealloc, Error **errp)
476
{
175
{
477
BDRVQcow2State *s = bs->opaque;
176
BDRVQcow2State *s = bs->opaque;
478
uint64_t old_length;
177
uint64_t old_length;
479
@@ -XXX,XX +XXX,XX @@ static int qcow2_truncate(BlockDriverState *bs, int64_t offset,
480
return -EINVAL;
481
}
482
483
+ qemu_co_mutex_lock(&s->lock);
484
+
485
/* cannot proceed if image has snapshots */
486
if (s->nb_snapshots) {
487
error_setg(errp, "Can't resize an image which has snapshots");
488
- return -ENOTSUP;
489
+ ret = -ENOTSUP;
490
+ goto fail;
491
}
492
493
/* cannot proceed if image has bitmaps */
494
if (s->nb_bitmaps) {
495
/* TODO: resize bitmaps in the image */
496
error_setg(errp, "Can't resize an image which has bitmaps");
497
- return -ENOTSUP;
498
+ ret = -ENOTSUP;
499
+ goto fail;
500
}
501
502
old_length = bs->total_sectors * 512;
503
@@ -XXX,XX +XXX,XX @@ static int qcow2_truncate(BlockDriverState *bs, int64_t offset,
504
if (prealloc != PREALLOC_MODE_OFF) {
505
error_setg(errp,
506
"Preallocation can't be used for shrinking an image");
507
- return -EINVAL;
508
+ ret = -EINVAL;
509
+ goto fail;
510
}
511
512
ret = qcow2_cluster_discard(bs, ROUND_UP(offset, s->cluster_size),
513
@@ -XXX,XX +XXX,XX @@ static int qcow2_truncate(BlockDriverState *bs, int64_t offset,
514
QCOW2_DISCARD_ALWAYS, true);
515
if (ret < 0) {
516
error_setg_errno(errp, -ret, "Failed to discard cropped clusters");
517
- return ret;
518
+ goto fail;
519
}
520
521
ret = qcow2_shrink_l1_table(bs, new_l1_size);
522
if (ret < 0) {
523
error_setg_errno(errp, -ret,
524
"Failed to reduce the number of L2 tables");
525
- return ret;
526
+ goto fail;
527
}
528
529
ret = qcow2_shrink_reftable(bs);
530
if (ret < 0) {
531
error_setg_errno(errp, -ret,
532
"Failed to discard unused refblocks");
533
- return ret;
534
+ goto fail;
535
}
536
537
old_file_size = bdrv_getlength(bs->file->bs);
538
if (old_file_size < 0) {
539
error_setg_errno(errp, -old_file_size,
540
"Failed to inquire current file length");
541
- return old_file_size;
542
+ ret = old_file_size;
543
+ goto fail;
544
}
545
last_cluster = qcow2_get_last_cluster(bs, old_file_size);
546
if (last_cluster < 0) {
547
error_setg_errno(errp, -last_cluster,
548
"Failed to find the last cluster");
549
- return last_cluster;
550
+ ret = last_cluster;
551
+ goto fail;
552
}
553
if ((last_cluster + 1) * s->cluster_size < old_file_size) {
554
Error *local_err = NULL;
555
556
- bdrv_truncate(bs->file, (last_cluster + 1) * s->cluster_size,
557
- PREALLOC_MODE_OFF, &local_err);
558
+ bdrv_co_truncate(bs->file, (last_cluster + 1) * s->cluster_size,
559
+ PREALLOC_MODE_OFF, &local_err);
560
if (local_err) {
561
warn_reportf_err(local_err,
562
"Failed to truncate the tail of the image: ");
563
@@ -XXX,XX +XXX,XX @@ static int qcow2_truncate(BlockDriverState *bs, int64_t offset,
564
ret = qcow2_grow_l1_table(bs, new_l1_size, true);
565
if (ret < 0) {
566
error_setg_errno(errp, -ret, "Failed to grow the L1 table");
567
- return ret;
568
+ goto fail;
569
}
570
}
571
572
@@ -XXX,XX +XXX,XX @@ static int qcow2_truncate(BlockDriverState *bs, int64_t offset,
573
ret = preallocate(bs, old_length, offset);
574
if (ret < 0) {
575
error_setg_errno(errp, -ret, "Preallocation failed");
576
- return ret;
577
+ goto fail;
578
}
579
break;
580
581
@@ -XXX,XX +XXX,XX @@ static int qcow2_truncate(BlockDriverState *bs, int64_t offset,
582
if (old_file_size < 0) {
583
error_setg_errno(errp, -old_file_size,
584
"Failed to inquire current file length");
585
- return old_file_size;
586
+ ret = old_file_size;
587
+ goto fail;
588
}
589
old_file_size = ROUND_UP(old_file_size, s->cluster_size);
590
591
@@ -XXX,XX +XXX,XX @@ static int qcow2_truncate(BlockDriverState *bs, int64_t offset,
592
if (allocation_start < 0) {
593
error_setg_errno(errp, -allocation_start,
594
"Failed to resize refcount structures");
595
- return allocation_start;
596
+ ret = allocation_start;
597
+ goto fail;
598
}
599
600
clusters_allocated = qcow2_alloc_clusters_at(bs, allocation_start,
601
@@ -XXX,XX +XXX,XX @@ static int qcow2_truncate(BlockDriverState *bs, int64_t offset,
602
if (clusters_allocated < 0) {
603
error_setg_errno(errp, -clusters_allocated,
604
"Failed to allocate data clusters");
605
- return clusters_allocated;
606
+ ret = clusters_allocated;
607
+ goto fail;
608
}
609
610
assert(clusters_allocated == nb_new_data_clusters);
611
@@ -XXX,XX +XXX,XX @@ static int qcow2_truncate(BlockDriverState *bs, int64_t offset,
612
/* Allocate the data area */
613
new_file_size = allocation_start +
614
nb_new_data_clusters * s->cluster_size;
615
- ret = bdrv_truncate(bs->file, new_file_size, prealloc, errp);
616
+ ret = bdrv_co_truncate(bs->file, new_file_size, prealloc, errp);
617
if (ret < 0) {
618
error_prepend(errp, "Failed to resize underlying file: ");
619
qcow2_free_clusters(bs, allocation_start,
620
nb_new_data_clusters * s->cluster_size,
621
QCOW2_DISCARD_OTHER);
622
- return ret;
623
+ goto fail;
624
}
625
626
/* Create the necessary L2 entries */
627
@@ -XXX,XX +XXX,XX @@ static int qcow2_truncate(BlockDriverState *bs, int64_t offset,
628
qcow2_free_clusters(bs, host_offset,
629
nb_new_data_clusters * s->cluster_size,
630
QCOW2_DISCARD_OTHER);
631
- return ret;
632
+ goto fail;
633
}
634
635
guest_offset += nb_clusters * s->cluster_size;
636
@@ -XXX,XX +XXX,XX @@ static int qcow2_truncate(BlockDriverState *bs, int64_t offset,
637
638
if (prealloc != PREALLOC_MODE_OFF) {
639
/* Flush metadata before actually changing the image size */
640
- ret = bdrv_flush(bs);
641
+ ret = qcow2_write_caches(bs);
642
if (ret < 0) {
643
error_setg_errno(errp, -ret,
644
"Failed to flush the preallocated area to disk");
645
- return ret;
646
+ goto fail;
647
}
648
}
649
650
@@ -XXX,XX +XXX,XX @@ static int qcow2_truncate(BlockDriverState *bs, int64_t offset,
651
&offset, sizeof(uint64_t));
652
if (ret < 0) {
653
error_setg_errno(errp, -ret, "Failed to update the image size");
654
- return ret;
655
+ goto fail;
656
}
657
658
s->l1_vm_state_index = new_l1_size;
659
- return 0;
660
+ ret = 0;
661
+fail:
662
+ qemu_co_mutex_unlock(&s->lock);
663
+ return ret;
664
}
665
666
/* XXX: put compressed sectors first, then all the cluster aligned
667
@@ -XXX,XX +XXX,XX @@ qcow2_co_pwritev_compressed(BlockDriverState *bs, uint64_t offset,
668
if (cluster_offset < 0) {
669
return cluster_offset;
670
}
671
- return bdrv_truncate(bs->file, cluster_offset, PREALLOC_MODE_OFF, NULL);
672
+ return bdrv_co_truncate(bs->file, cluster_offset, PREALLOC_MODE_OFF,
673
+ NULL);
674
}
675
676
if (offset_into_cluster(s, offset)) {
677
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_qcow2 = {
678
.bdrv_co_pdiscard = qcow2_co_pdiscard,
679
.bdrv_co_copy_range_from = qcow2_co_copy_range_from,
680
.bdrv_co_copy_range_to = qcow2_co_copy_range_to,
681
- .bdrv_truncate = qcow2_truncate,
682
+ .bdrv_co_truncate = qcow2_co_truncate,
683
.bdrv_co_pwritev_compressed = qcow2_co_pwritev_compressed,
684
.bdrv_make_empty = qcow2_make_empty,
685
686
diff --git a/block/qed.c b/block/qed.c
178
diff --git a/block/qed.c b/block/qed.c
687
index XXXXXXX..XXXXXXX 100644
179
index XXXXXXX..XXXXXXX 100644
688
--- a/block/qed.c
180
--- a/block/qed.c
689
+++ b/block/qed.c
181
+++ b/block/qed.c
690
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_qed_co_pwrite_zeroes(BlockDriverState *bs,
182
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_qed_co_truncate(BlockDriverState *bs,
691
QED_AIOCB_WRITE | QED_AIOCB_ZERO);
183
int64_t offset,
692
}
184
bool exact,
693
185
PreallocMode prealloc,
694
-static int bdrv_qed_truncate(BlockDriverState *bs, int64_t offset,
186
+ BdrvRequestFlags flags,
695
- PreallocMode prealloc, Error **errp)
187
Error **errp)
696
+static int coroutine_fn bdrv_qed_co_truncate(BlockDriverState *bs,
697
+ int64_t offset,
698
+ PreallocMode prealloc,
699
+ Error **errp)
700
{
188
{
701
BDRVQEDState *s = bs->opaque;
189
BDRVQEDState *s = bs->opaque;
702
uint64_t old_image_size;
703
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_qed = {
704
.bdrv_co_readv = bdrv_qed_co_readv,
705
.bdrv_co_writev = bdrv_qed_co_writev,
706
.bdrv_co_pwrite_zeroes = bdrv_qed_co_pwrite_zeroes,
707
- .bdrv_truncate = bdrv_qed_truncate,
708
+ .bdrv_co_truncate = bdrv_qed_co_truncate,
709
.bdrv_getlength = bdrv_qed_getlength,
710
.bdrv_get_info = bdrv_qed_get_info,
711
.bdrv_refresh_limits = bdrv_qed_refresh_limits,
712
diff --git a/block/raw-format.c b/block/raw-format.c
190
diff --git a/block/raw-format.c b/block/raw-format.c
713
index XXXXXXX..XXXXXXX 100644
191
index XXXXXXX..XXXXXXX 100644
714
--- a/block/raw-format.c
192
--- a/block/raw-format.c
715
+++ b/block/raw-format.c
193
+++ b/block/raw-format.c
716
@@ -XXX,XX +XXX,XX @@ static void raw_refresh_limits(BlockDriverState *bs, Error **errp)
194
@@ -XXX,XX +XXX,XX @@ static void raw_refresh_limits(BlockDriverState *bs, Error **errp)
717
}
195
718
}
196
static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset,
719
197
bool exact, PreallocMode prealloc,
720
-static int raw_truncate(BlockDriverState *bs, int64_t offset,
198
- Error **errp)
721
- PreallocMode prealloc, Error **errp)
199
+ BdrvRequestFlags flags, Error **errp)
722
+static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset,
723
+ PreallocMode prealloc, Error **errp)
724
{
200
{
725
BDRVRawState *s = bs->opaque;
201
BDRVRawState *s = bs->opaque;
726
202
727
@@ -XXX,XX +XXX,XX @@ static int raw_truncate(BlockDriverState *bs, int64_t offset,
728
729
s->size = offset;
730
offset += s->offset;
731
- return bdrv_truncate(bs->file, offset, prealloc, errp);
732
+ return bdrv_co_truncate(bs->file, offset, prealloc, errp);
733
}
734
735
static void raw_eject(BlockDriverState *bs, bool eject_flag)
736
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_raw = {
737
.bdrv_co_block_status = &raw_co_block_status,
738
.bdrv_co_copy_range_from = &raw_co_copy_range_from,
739
.bdrv_co_copy_range_to = &raw_co_copy_range_to,
740
- .bdrv_truncate = &raw_truncate,
741
+ .bdrv_co_truncate = &raw_co_truncate,
742
.bdrv_getlength = &raw_getlength,
743
.has_variable_length = true,
744
.bdrv_measure = &raw_measure,
745
diff --git a/block/rbd.c b/block/rbd.c
203
diff --git a/block/rbd.c b/block/rbd.c
746
index XXXXXXX..XXXXXXX 100644
204
index XXXXXXX..XXXXXXX 100644
747
--- a/block/rbd.c
205
--- a/block/rbd.c
748
+++ b/block/rbd.c
206
+++ b/block/rbd.c
749
@@ -XXX,XX +XXX,XX @@ static int64_t qemu_rbd_getlength(BlockDriverState *bs)
207
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qemu_rbd_co_truncate(BlockDriverState *bs,
750
return info.size;
208
int64_t offset,
751
}
209
bool exact,
752
210
PreallocMode prealloc,
753
-static int qemu_rbd_truncate(BlockDriverState *bs, int64_t offset,
211
+ BdrvRequestFlags flags,
754
- PreallocMode prealloc, Error **errp)
212
Error **errp)
755
+static int coroutine_fn qemu_rbd_co_truncate(BlockDriverState *bs,
213
{
756
+ int64_t offset,
757
+ PreallocMode prealloc,
758
+ Error **errp)
759
{
760
BDRVRBDState *s = bs->opaque;
761
int r;
214
int r;
762
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_rbd = {
763
.bdrv_get_info = qemu_rbd_getinfo,
764
.create_opts = &qemu_rbd_create_opts,
765
.bdrv_getlength = qemu_rbd_getlength,
766
- .bdrv_truncate = qemu_rbd_truncate,
767
+ .bdrv_co_truncate = qemu_rbd_co_truncate,
768
.protocol_name = "rbd",
769
770
.bdrv_aio_preadv = qemu_rbd_aio_preadv,
771
diff --git a/block/sheepdog.c b/block/sheepdog.c
215
diff --git a/block/sheepdog.c b/block/sheepdog.c
772
index XXXXXXX..XXXXXXX 100644
216
index XXXXXXX..XXXXXXX 100644
773
--- a/block/sheepdog.c
217
--- a/block/sheepdog.c
774
+++ b/block/sheepdog.c
218
+++ b/block/sheepdog.c
775
@@ -XXX,XX +XXX,XX @@ static int64_t sd_getlength(BlockDriverState *bs)
219
@@ -XXX,XX +XXX,XX @@ static int64_t sd_getlength(BlockDriverState *bs)
776
return s->inode.vdi_size;
220
777
}
221
static int coroutine_fn sd_co_truncate(BlockDriverState *bs, int64_t offset,
778
222
bool exact, PreallocMode prealloc,
779
-static int sd_truncate(BlockDriverState *bs, int64_t offset,
223
- Error **errp)
780
- PreallocMode prealloc, Error **errp)
224
+ BdrvRequestFlags flags, Error **errp)
781
+static int coroutine_fn sd_co_truncate(BlockDriverState *bs, int64_t offset,
782
+ PreallocMode prealloc, Error **errp)
783
{
225
{
784
BDRVSheepdogState *s = bs->opaque;
226
BDRVSheepdogState *s = bs->opaque;
785
int ret, fd;
227
int ret, fd;
786
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int sd_co_writev(BlockDriverState *bs, int64_t sector_num,
228
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int sd_co_writev(BlockDriverState *bs, int64_t sector_num,
787
229
788
assert(!flags);
230
assert(!flags);
789
if (offset > s->inode.vdi_size) {
231
if (offset > s->inode.vdi_size) {
790
- ret = sd_truncate(bs, offset, PREALLOC_MODE_OFF, NULL);
232
- ret = sd_co_truncate(bs, offset, false, PREALLOC_MODE_OFF, NULL);
791
+ ret = sd_co_truncate(bs, offset, PREALLOC_MODE_OFF, NULL);
233
+ ret = sd_co_truncate(bs, offset, false, PREALLOC_MODE_OFF, 0, NULL);
792
if (ret < 0) {
234
if (ret < 0) {
793
return ret;
235
return ret;
794
}
236
}
795
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_sheepdog = {
796
.bdrv_has_zero_init = bdrv_has_zero_init_1,
797
.bdrv_getlength = sd_getlength,
798
.bdrv_get_allocated_file_size = sd_get_allocated_file_size,
799
- .bdrv_truncate = sd_truncate,
800
+ .bdrv_co_truncate = sd_co_truncate,
801
802
.bdrv_co_readv = sd_co_readv,
803
.bdrv_co_writev = sd_co_writev,
804
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_sheepdog_tcp = {
805
.bdrv_has_zero_init = bdrv_has_zero_init_1,
806
.bdrv_getlength = sd_getlength,
807
.bdrv_get_allocated_file_size = sd_get_allocated_file_size,
808
- .bdrv_truncate = sd_truncate,
809
+ .bdrv_co_truncate = sd_co_truncate,
810
811
.bdrv_co_readv = sd_co_readv,
812
.bdrv_co_writev = sd_co_writev,
813
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_sheepdog_unix = {
814
.bdrv_has_zero_init = bdrv_has_zero_init_1,
815
.bdrv_getlength = sd_getlength,
816
.bdrv_get_allocated_file_size = sd_get_allocated_file_size,
817
- .bdrv_truncate = sd_truncate,
818
+ .bdrv_co_truncate = sd_co_truncate,
819
820
.bdrv_co_readv = sd_co_readv,
821
.bdrv_co_writev = sd_co_writev,
822
diff --git a/block/ssh.c b/block/ssh.c
237
diff --git a/block/ssh.c b/block/ssh.c
823
index XXXXXXX..XXXXXXX 100644
238
index XXXXXXX..XXXXXXX 100644
824
--- a/block/ssh.c
239
--- a/block/ssh.c
825
+++ b/block/ssh.c
240
+++ b/block/ssh.c
826
@@ -XXX,XX +XXX,XX @@ static int64_t ssh_getlength(BlockDriverState *bs)
241
@@ -XXX,XX +XXX,XX @@ static int64_t ssh_getlength(BlockDriverState *bs)
827
return length;
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;
828
}
263
}
829
830
-static int ssh_truncate(BlockDriverState *bs, int64_t offset,
831
- PreallocMode prealloc, Error **errp)
832
+static int coroutine_fn ssh_co_truncate(BlockDriverState *bs, int64_t offset,
833
+ PreallocMode prealloc, Error **errp)
834
{
835
BDRVSSHState *s = bs->opaque;
836
837
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_ssh = {
838
.bdrv_co_readv = ssh_co_readv,
839
.bdrv_co_writev = ssh_co_writev,
840
.bdrv_getlength = ssh_getlength,
841
- .bdrv_truncate = ssh_truncate,
842
+ .bdrv_co_truncate = ssh_co_truncate,
843
.bdrv_co_flush_to_disk = ssh_co_flush,
844
.create_opts = &ssh_create_opts,
845
};
846
--
264
--
847
2.13.6
265
2.25.3
848
266
849
267
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
1
Now that block drivers can support flags for .bdrv_co_truncate, expose
2
the parameter in the node level interfaces bdrv_co_truncate() and
3
bdrv_truncate().
2
4
3
We are gradually moving away from sector-based interfaces, towards
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
byte-based. Now that all callers of vectored I/O have been converted
6
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
5
to use our preferred byte-based bdrv_co_p{read,write}v(), we can
7
Reviewed-by: Alberto Garcia <berto@igalia.com>
6
delete the unused bdrv_co_{read,write}v().
8
Reviewed-by: Max Reitz <mreitz@redhat.com>
7
9
Message-Id: <20200424125448.63318-3-kwolf@redhat.com>
8
Furthermore, this gets rid of the signature difference between the
9
public bdrv_co_writev() and the callback .bdrv_co_writev (the
10
latter still exists, because some drivers still need more work
11
before they are fully byte-based).
12
13
Signed-off-by: Eric Blake <eblake@redhat.com>
14
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
15
Reviewed-by: Jeff Cody <jcody@redhat.com>
16
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
17
---
11
---
18
include/block/block.h | 4 ----
12
include/block/block.h | 5 +++--
19
block/io.c | 36 ------------------------------------
13
block/block-backend.c | 2 +-
20
2 files changed, 40 deletions(-)
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(-)
21
26
22
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
23
index XXXXXXX..XXXXXXX 100644
28
index XXXXXXX..XXXXXXX 100644
24
--- a/include/block/block.h
29
--- a/include/block/block.h
25
+++ b/include/block/block.h
30
+++ b/include/block/block.h
26
@@ -XXX,XX +XXX,XX @@ int bdrv_pwrite(BdrvChild *child, int64_t offset, const void *buf, int bytes);
31
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs,
27
int bdrv_pwritev(BdrvChild *child, int64_t offset, QEMUIOVector *qiov);
32
void bdrv_refresh_filename(BlockDriverState *bs);
28
int bdrv_pwrite_sync(BdrvChild *child, int64_t offset,
33
29
const void *buf, int count);
34
int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
30
-int coroutine_fn bdrv_co_readv(BdrvChild *child, int64_t sector_num,
35
- PreallocMode prealloc, Error **errp);
31
- int nb_sectors, QEMUIOVector *qiov);
36
+ PreallocMode prealloc, BdrvRequestFlags flags,
32
-int coroutine_fn bdrv_co_writev(BdrvChild *child, int64_t sector_num,
37
+ Error **errp);
33
- int nb_sectors, QEMUIOVector *qiov);
38
int bdrv_truncate(BdrvChild *child, int64_t offset, bool exact,
34
/*
39
- PreallocMode prealloc, Error **errp);
35
* Efficiently zero a region of the disk image. Note that this is a regular
40
+ PreallocMode prealloc, BdrvRequestFlags flags, Error **errp);
36
* I/O request like read or write and should have a reasonable size. This
41
42
int64_t bdrv_nb_sectors(BlockDriverState *bs);
43
int64_t bdrv_getlength(BlockDriverState *bs);
44
diff --git a/block/block-backend.c b/block/block-backend.c
45
index XXXXXXX..XXXXXXX 100644
46
--- a/block/block-backend.c
47
+++ b/block/block-backend.c
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)
37
diff --git a/block/io.c b/block/io.c
70
diff --git a/block/io.c b/block/io.c
38
index XXXXXXX..XXXXXXX 100644
71
index XXXXXXX..XXXXXXX 100644
39
--- a/block/io.c
72
--- a/block/io.c
40
+++ b/block/io.c
73
+++ b/block/io.c
41
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_preadv(BdrvChild *child,
74
@@ -XXX,XX +XXX,XX @@ static void bdrv_parent_cb_resize(BlockDriverState *bs)
42
return ret;
75
* 'offset' bytes in length.
43
}
76
*/
44
77
int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
45
-static int coroutine_fn bdrv_co_do_readv(BdrvChild *child,
78
- PreallocMode prealloc, Error **errp)
46
- int64_t sector_num, int nb_sectors, QEMUIOVector *qiov,
79
+ PreallocMode prealloc, BdrvRequestFlags flags,
47
- BdrvRequestFlags flags)
80
+ Error **errp)
48
-{
49
- if (nb_sectors < 0 || nb_sectors > BDRV_REQUEST_MAX_SECTORS) {
50
- return -EINVAL;
51
- }
52
-
53
- return bdrv_co_preadv(child, sector_num << BDRV_SECTOR_BITS,
54
- nb_sectors << BDRV_SECTOR_BITS, qiov, flags);
55
-}
56
-
57
-int coroutine_fn bdrv_co_readv(BdrvChild *child, int64_t sector_num,
58
- int nb_sectors, QEMUIOVector *qiov)
59
-{
60
- return bdrv_co_do_readv(child, sector_num, nb_sectors, qiov, 0);
61
-}
62
-
63
static int coroutine_fn bdrv_co_do_pwrite_zeroes(BlockDriverState *bs,
64
int64_t offset, int bytes, BdrvRequestFlags flags)
65
{
81
{
66
@@ -XXX,XX +XXX,XX @@ out:
82
BlockDriverState *bs = child->bs;
67
return ret;
83
BlockDriver *drv = bs->drv;
68
}
84
BdrvTrackedRequest req;
69
85
- BdrvRequestFlags flags = 0;
70
-static int coroutine_fn bdrv_co_do_writev(BdrvChild *child,
86
int64_t old_size, new_bytes;
71
- int64_t sector_num, int nb_sectors, QEMUIOVector *qiov,
87
int ret;
72
- BdrvRequestFlags flags)
88
73
-{
89
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
74
- if (nb_sectors < 0 || nb_sectors > BDRV_REQUEST_MAX_SECTORS) {
90
}
75
- return -EINVAL;
91
ret = drv->bdrv_co_truncate(bs, offset, exact, prealloc, flags, errp);
76
- }
92
} else if (bs->file && drv->is_filter) {
77
-
93
- ret = bdrv_co_truncate(bs->file, offset, exact, prealloc, errp);
78
- return bdrv_co_pwritev(child, sector_num << BDRV_SECTOR_BITS,
94
+ ret = bdrv_co_truncate(bs->file, offset, exact, prealloc, flags, errp);
79
- nb_sectors << BDRV_SECTOR_BITS, qiov, flags);
95
} else {
80
-}
96
error_setg(errp, "Image format driver does not support resize");
81
-
97
ret = -ENOTSUP;
82
-int coroutine_fn bdrv_co_writev(BdrvChild *child, int64_t sector_num,
98
@@ -XXX,XX +XXX,XX @@ typedef struct TruncateCo {
83
- int nb_sectors, QEMUIOVector *qiov)
99
int64_t offset;
84
-{
100
bool exact;
85
- return bdrv_co_do_writev(child, sector_num, nb_sectors, qiov, 0);
101
PreallocMode prealloc;
86
-}
102
+ BdrvRequestFlags flags;
87
-
103
Error **errp;
88
int coroutine_fn bdrv_co_pwrite_zeroes(BdrvChild *child, int64_t offset,
104
int ret;
89
int bytes, BdrvRequestFlags flags)
105
} TruncateCo;
106
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn bdrv_truncate_co_entry(void *opaque)
90
{
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;
91
--
334
--
92
2.13.6
335
2.25.3
93
336
94
337
diff view generated by jsdifflib
1
From: Markus Armbruster <armbru@redhat.com>
1
Now that node level interface bdrv_truncate() supports passing request
2
2
flags to the block driver, expose this on the BlockBackend level, too.
3
block_crypto_open_opts_init() and block_crypto_create_opts_init()
3
4
contain a virtual visit of QCryptoBlockOptions and
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
QCryptoBlockCreateOptions less member "format", respectively.
5
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
6
6
Reviewed-by: Alberto Garcia <berto@igalia.com>
7
Change their callers to put member "format" in the QDict, so they can
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
8
use the generated visitors for these types instead.
8
Message-Id: <20200424125448.63318-4-kwolf@redhat.com>
9
10
Signed-off-by: Markus Armbruster <armbru@redhat.com>
11
Reviewed-by: Eric Blake <eblake@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
---
10
---
14
block/crypto.h | 8 ++---
11
include/sysemu/block-backend.h | 2 +-
15
block/crypto.c | 99 +++++++++-------------------------------------------------
12
block.c | 3 ++-
16
block/qcow.c | 5 ++-
13
block/block-backend.c | 4 ++--
17
block/qcow2.c | 10 +++---
14
block/commit.c | 4 ++--
18
4 files changed, 22 insertions(+), 100 deletions(-)
15
block/crypto.c | 2 +-
19
16
block/mirror.c | 2 +-
20
diff --git a/block/crypto.h b/block/crypto.h
17
block/qcow2.c | 4 ++--
21
index XXXXXXX..XXXXXXX 100644
18
block/qed.c | 2 +-
22
--- a/block/crypto.h
19
block/vdi.c | 2 +-
23
+++ b/block/crypto.h
20
block/vhdx.c | 4 ++--
24
@@ -XXX,XX +XXX,XX @@
21
block/vmdk.c | 6 +++---
25
}
22
block/vpc.c | 2 +-
26
23
blockdev.c | 2 +-
27
QCryptoBlockCreateOptions *
24
qemu-img.c | 2 +-
28
-block_crypto_create_opts_init(QCryptoBlockFormat format,
25
qemu-io-cmds.c | 2 +-
29
- QDict *opts,
26
15 files changed, 22 insertions(+), 21 deletions(-)
30
- Error **errp);
27
31
+block_crypto_create_opts_init(QDict *opts, Error **errp);
28
diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h
32
29
index XXXXXXX..XXXXXXX 100644
33
QCryptoBlockOpenOptions *
30
--- a/include/sysemu/block-backend.h
34
-block_crypto_open_opts_init(QCryptoBlockFormat format,
31
+++ b/include/sysemu/block-backend.h
35
- QDict *opts,
32
@@ -XXX,XX +XXX,XX @@ int coroutine_fn blk_co_pwrite_zeroes(BlockBackend *blk, int64_t offset,
36
- Error **errp);
33
int blk_pwrite_compressed(BlockBackend *blk, int64_t offset, const void *buf,
37
+block_crypto_open_opts_init(QDict *opts, Error **errp);
34
int bytes);
38
35
int blk_truncate(BlockBackend *blk, int64_t offset, bool exact,
39
#endif /* BLOCK_CRYPTO_H__ */
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);
40
diff --git a/block/crypto.c b/block/crypto.c
98
diff --git a/block/crypto.c b/block/crypto.c
41
index XXXXXXX..XXXXXXX 100644
99
index XXXXXXX..XXXXXXX 100644
42
--- a/block/crypto.c
100
--- a/block/crypto.c
43
+++ b/block/crypto.c
101
+++ b/block/crypto.c
44
@@ -XXX,XX +XXX,XX @@ static QemuOptsList block_crypto_create_opts_luks = {
102
@@ -XXX,XX +XXX,XX @@ static ssize_t block_crypto_init_func(QCryptoBlock *block,
45
103
* which will be used by the crypto header
46
104
*/
47
QCryptoBlockOpenOptions *
105
return blk_truncate(data->blk, data->size + headerlen, false,
48
-block_crypto_open_opts_init(QCryptoBlockFormat format,
106
- data->prealloc, errp);
49
- QDict *opts,
107
+ data->prealloc, 0, errp);
50
- Error **errp)
51
+block_crypto_open_opts_init(QDict *opts, Error **errp)
52
{
53
Visitor *v;
54
- QCryptoBlockOpenOptions *ret = NULL;
55
- Error *local_err = NULL;
56
-
57
- ret = g_new0(QCryptoBlockOpenOptions, 1);
58
- ret->format = format;
59
+ QCryptoBlockOpenOptions *ret;
60
61
- v = qobject_input_visitor_new_flat_confused(opts, &local_err);
62
+ v = qobject_input_visitor_new_flat_confused(opts, errp);
63
if (!v) {
64
- goto out;
65
- }
66
-
67
- visit_start_struct(v, NULL, NULL, 0, &local_err);
68
- if (local_err) {
69
- goto out;
70
- }
71
-
72
- switch (format) {
73
- case Q_CRYPTO_BLOCK_FORMAT_LUKS:
74
- visit_type_QCryptoBlockOptionsLUKS_members(
75
- v, &ret->u.luks, &local_err);
76
- break;
77
-
78
- case Q_CRYPTO_BLOCK_FORMAT_QCOW:
79
- visit_type_QCryptoBlockOptionsQCow_members(
80
- v, &ret->u.qcow, &local_err);
81
- break;
82
-
83
- default:
84
- error_setg(&local_err, "Unsupported block format %d", format);
85
- break;
86
- }
87
- if (!local_err) {
88
- visit_check_struct(v, &local_err);
89
+ return NULL;
90
}
91
92
- visit_end_struct(v, NULL);
93
+ visit_type_QCryptoBlockOpenOptions(v, NULL, &ret, errp);
94
95
- out:
96
- if (local_err) {
97
- error_propagate(errp, local_err);
98
- qapi_free_QCryptoBlockOpenOptions(ret);
99
- ret = NULL;
100
- }
101
visit_free(v);
102
return ret;
103
}
108
}
104
109
105
110
106
QCryptoBlockCreateOptions *
111
diff --git a/block/mirror.c b/block/mirror.c
107
-block_crypto_create_opts_init(QCryptoBlockFormat format,
112
index XXXXXXX..XXXXXXX 100644
108
- QDict *opts,
113
--- a/block/mirror.c
109
- Error **errp)
114
+++ b/block/mirror.c
110
+block_crypto_create_opts_init(QDict *opts, Error **errp)
115
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn mirror_run(Job *job, Error **errp)
111
{
116
112
Visitor *v;
117
if (s->bdev_length > base_length) {
113
- QCryptoBlockCreateOptions *ret = NULL;
118
ret = blk_truncate(s->target, s->bdev_length, false,
114
- Error *local_err = NULL;
119
- PREALLOC_MODE_OFF, NULL);
115
-
120
+ PREALLOC_MODE_OFF, 0, NULL);
116
- ret = g_new0(QCryptoBlockCreateOptions, 1);
121
if (ret < 0) {
117
- ret->format = format;
122
goto immediate_exit;
118
+ QCryptoBlockCreateOptions *ret;
119
120
- v = qobject_input_visitor_new_flat_confused(opts, &local_err);
121
+ v = qobject_input_visitor_new_flat_confused(opts, errp);
122
if (!v) {
123
- goto out;
124
- }
125
-
126
- visit_start_struct(v, NULL, NULL, 0, &local_err);
127
- if (local_err) {
128
- goto out;
129
- }
130
-
131
- switch (format) {
132
- case Q_CRYPTO_BLOCK_FORMAT_LUKS:
133
- visit_type_QCryptoBlockCreateOptionsLUKS_members(
134
- v, &ret->u.luks, &local_err);
135
- break;
136
-
137
- case Q_CRYPTO_BLOCK_FORMAT_QCOW:
138
- visit_type_QCryptoBlockOptionsQCow_members(
139
- v, &ret->u.qcow, &local_err);
140
- break;
141
-
142
- default:
143
- error_setg(&local_err, "Unsupported block format %d", format);
144
- break;
145
- }
146
- if (!local_err) {
147
- visit_check_struct(v, &local_err);
148
+ return NULL;
149
}
150
151
- visit_end_struct(v, NULL);
152
+ visit_type_QCryptoBlockCreateOptions(v, NULL, &ret, errp);
153
154
- out:
155
- if (local_err) {
156
- error_propagate(errp, local_err);
157
- qapi_free_QCryptoBlockCreateOptions(ret);
158
- ret = NULL;
159
- }
160
visit_free(v);
161
return ret;
162
}
163
@@ -XXX,XX +XXX,XX @@ static int block_crypto_open_generic(QCryptoBlockFormat format,
164
}
165
166
cryptoopts = qemu_opts_to_qdict(opts, NULL);
167
+ qdict_put_str(cryptoopts, "format", QCryptoBlockFormat_str(format));
168
169
- open_opts = block_crypto_open_opts_init(format, cryptoopts, errp);
170
+ open_opts = block_crypto_open_opts_init(cryptoopts, errp);
171
if (!open_opts) {
172
goto cleanup;
173
}
174
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn block_crypto_co_create_opts_luks(const char *filename,
175
&block_crypto_create_opts_luks,
176
true);
177
178
- create_opts = block_crypto_create_opts_init(Q_CRYPTO_BLOCK_FORMAT_LUKS,
179
- cryptoopts, errp);
180
+ qdict_put_str(cryptoopts, "format", "luks");
181
+ create_opts = block_crypto_create_opts_init(cryptoopts, errp);
182
if (!create_opts) {
183
ret = -EINVAL;
184
goto fail;
185
diff --git a/block/qcow.c b/block/qcow.c
186
index XXXXXXX..XXXXXXX 100644
187
--- a/block/qcow.c
188
+++ b/block/qcow.c
189
@@ -XXX,XX +XXX,XX @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags,
190
ret = -EINVAL;
191
goto fail;
192
}
123
}
193
- qdict_del(encryptopts, "format");
194
- crypto_opts = block_crypto_open_opts_init(
195
- Q_CRYPTO_BLOCK_FORMAT_QCOW, encryptopts, errp);
196
+ qdict_put_str(encryptopts, "format", "qcow");
197
+ crypto_opts = block_crypto_open_opts_init(encryptopts, errp);
198
if (!crypto_opts) {
199
ret = -EINVAL;
200
goto fail;
201
diff --git a/block/qcow2.c b/block/qcow2.c
124
diff --git a/block/qcow2.c b/block/qcow2.c
202
index XXXXXXX..XXXXXXX 100644
125
index XXXXXXX..XXXXXXX 100644
203
--- a/block/qcow2.c
126
--- a/block/qcow2.c
204
+++ b/block/qcow2.c
127
+++ b/block/qcow2.c
205
@@ -XXX,XX +XXX,XX @@ static int qcow2_update_options_prepare(BlockDriverState *bs,
128
@@ -XXX,XX +XXX,XX @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp)
206
ret = -EINVAL;
129
207
goto fail;
130
/* Okay, now that we have a valid image, let's give it the right size */
208
}
131
ret = blk_truncate(blk, qcow2_opts->size, false, qcow2_opts->preallocation,
209
- qdict_del(encryptopts, "format");
132
- errp);
210
- r->crypto_opts = block_crypto_open_opts_init(
133
+ 0, errp);
211
- Q_CRYPTO_BLOCK_FORMAT_QCOW, encryptopts, errp);
134
if (ret < 0) {
212
+ qdict_put_str(encryptopts, "format", "qcow");
135
error_prepend(errp, "Could not resize image: ");
213
+ r->crypto_opts = block_crypto_open_opts_init(encryptopts, errp);
136
goto out;
214
break;
137
@@ -XXX,XX +XXX,XX @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts,
215
138
* Amending image options should ensure that the image has
216
case QCOW_CRYPT_LUKS:
139
* exactly the given new values, so pass exact=true here.
217
@@ -XXX,XX +XXX,XX @@ static int qcow2_update_options_prepare(BlockDriverState *bs,
140
*/
218
ret = -EINVAL;
141
- ret = blk_truncate(blk, new_size, true, PREALLOC_MODE_OFF, errp);
219
goto fail;
142
+ ret = blk_truncate(blk, new_size, true, PREALLOC_MODE_OFF, 0, errp);
220
}
143
blk_unref(blk);
221
- qdict_del(encryptopts, "format");
144
if (ret < 0) {
222
- r->crypto_opts = block_crypto_open_opts_init(
145
return ret;
223
- Q_CRYPTO_BLOCK_FORMAT_LUKS, encryptopts, errp);
146
diff --git a/block/qed.c b/block/qed.c
224
+ qdict_put_str(encryptopts, "format", "luks");
147
index XXXXXXX..XXXXXXX 100644
225
+ r->crypto_opts = block_crypto_open_opts_init(encryptopts, errp);
148
--- a/block/qed.c
226
break;
149
+++ b/block/qed.c
227
150
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_qed_co_create(BlockdevCreateOptions *opts,
228
default:
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;
229
--
275
--
230
2.13.6
276
2.25.3
231
277
232
278
diff view generated by jsdifflib
1
If we managed to allocate the clusters, but then failed to write the
1
If BDRV_REQ_ZERO_WRITE is set and we're extending the image, calling
2
data, there's a good chance that we'll still be able to free the
2
qcow2_cluster_zeroize() with flags=0 does the right thing: It doesn't
3
clusters again in order to avoid cluster leaks (the refcounts are
3
undo any previous preallocation, but just adds the zero flag to all
4
cached, so even if we can't write them out right now, we may be able to
4
relevant L2 entries. If an external data file is in use, a write_zeroes
5
do so when the VM is resumed after a werror=stop/enospc pause).
5
request to the data file is made instead.
6
6
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
Message-Id: <20200424125448.63318-5-kwolf@redhat.com>
9
Reviewed-by: Eric Blake <eblake@redhat.com>
8
Reviewed-by: Max Reitz <mreitz@redhat.com>
10
Reviewed-by: Max Reitz <mreitz@redhat.com>
9
Reviewed-by: Eric Blake <eblake@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
Tested-by: Eric Blake <eblake@redhat.com>
11
---
12
---
12
block/qcow2.h | 1 +
13
block/qcow2-cluster.c | 2 +-
13
block/qcow2-cluster.c | 11 +++++++++++
14
block/qcow2.c | 34 ++++++++++++++++++++++++++++++++++
14
block/qcow2.c | 2 ++
15
2 files changed, 35 insertions(+), 1 deletion(-)
15
3 files changed, 14 insertions(+)
16
16
17
diff --git a/block/qcow2.h b/block/qcow2.h
18
index XXXXXXX..XXXXXXX 100644
19
--- a/block/qcow2.h
20
+++ b/block/qcow2.h
21
@@ -XXX,XX +XXX,XX @@ uint64_t qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs,
22
int compressed_size);
23
24
int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m);
25
+void qcow2_alloc_cluster_abort(BlockDriverState *bs, QCowL2Meta *m);
26
int qcow2_cluster_discard(BlockDriverState *bs, uint64_t offset,
27
uint64_t bytes, enum qcow2_discard_type type,
28
bool full_discard);
29
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
17
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
30
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
31
--- a/block/qcow2-cluster.c
19
--- a/block/qcow2-cluster.c
32
+++ b/block/qcow2-cluster.c
20
+++ b/block/qcow2-cluster.c
33
@@ -XXX,XX +XXX,XX @@ err:
21
@@ -XXX,XX +XXX,XX @@ int qcow2_cluster_zeroize(BlockDriverState *bs, uint64_t offset,
34
return ret;
22
/* Caller must pass aligned values, except at image end */
35
}
23
assert(QEMU_IS_ALIGNED(offset, s->cluster_size));
36
24
assert(QEMU_IS_ALIGNED(end_offset, s->cluster_size) ||
37
+/**
25
- end_offset == bs->total_sectors << BDRV_SECTOR_BITS);
38
+ * Frees the allocated clusters because the request failed and they won't
26
+ end_offset >= bs->total_sectors << BDRV_SECTOR_BITS);
39
+ * actually be linked.
27
40
+ */
28
/* The zero flag is only supported by version 3 and newer */
41
+void qcow2_alloc_cluster_abort(BlockDriverState *bs, QCowL2Meta *m)
29
if (s->qcow_version < 3) {
42
+{
43
+ BDRVQcow2State *s = bs->opaque;
44
+ qcow2_free_clusters(bs, m->alloc_offset, m->nb_clusters << s->cluster_bits,
45
+ QCOW2_DISCARD_NEVER);
46
+}
47
+
48
/*
49
* Returns the number of contiguous clusters that can be used for an allocating
50
* write, but require COW to be performed (this includes yet unallocated space,
51
diff --git a/block/qcow2.c b/block/qcow2.c
30
diff --git a/block/qcow2.c b/block/qcow2.c
52
index XXXXXXX..XXXXXXX 100644
31
index XXXXXXX..XXXXXXX 100644
53
--- a/block/qcow2.c
32
--- a/block/qcow2.c
54
+++ b/block/qcow2.c
33
+++ b/block/qcow2.c
55
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_handle_l2meta(BlockDriverState *bs,
34
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
56
if (ret) {
35
57
goto out;
36
bs->supported_zero_flags = header.version >= 3 ?
58
}
37
BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK : 0;
59
+ } else {
38
+ bs->supported_truncate_flags = BDRV_REQ_ZERO_WRITE;
60
+ qcow2_alloc_cluster_abort(bs, l2meta);
39
61
}
40
/* Repair image if dirty */
62
41
if (!(flags & (BDRV_O_CHECK | BDRV_O_INACTIVE)) && !bs->read_only &&
63
/* Take the request off the list of running requests */
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;
75
+ }
76
+ }
77
+ }
78
+
79
if (prealloc != PREALLOC_MODE_OFF) {
80
/* Flush metadata before actually changing the image size */
81
ret = qcow2_write_caches(bs);
64
--
82
--
65
2.13.6
83
2.25.3
66
84
67
85
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
1
The raw format driver can simply forward the flag and let its bs->file
2
child take care of actually providing the zeros.
2
3
3
We are gradually moving away from sector-based interfaces, towards
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
byte-based. The qcow driver is now ready to fully utilize the
5
Reviewed-by: Max Reitz <mreitz@redhat.com>
5
byte-based callback interface, as long as we override the default
6
Reviewed-by: Eric Blake <eblake@redhat.com>
6
alignment to still be 512 (needed at least for asserts present
7
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
7
because of encryption, but easier to do everywhere than to audit
8
Message-Id: <20200424125448.63318-6-kwolf@redhat.com>
8
which sub-sector requests are handled correctly, especially since
9
we no longer recommend qcow for new disk images).
10
11
Signed-off-by: Eric Blake <eblake@redhat.com>
12
Reviewed-by: Jeff Cody <jcody@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
---
10
---
15
block/qcow.c | 35 ++++++++++++++++++++---------------
11
block/raw-format.c | 4 +++-
16
1 file changed, 20 insertions(+), 15 deletions(-)
12
1 file changed, 3 insertions(+), 1 deletion(-)
17
13
18
diff --git a/block/qcow.c b/block/qcow.c
14
diff --git a/block/raw-format.c b/block/raw-format.c
19
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
20
--- a/block/qcow.c
16
--- a/block/raw-format.c
21
+++ b/block/qcow.c
17
+++ b/block/raw-format.c
22
@@ -XXX,XX +XXX,XX @@ typedef struct QCowHeader {
18
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset,
23
typedef struct BDRVQcowState {
19
24
int cluster_bits;
20
s->size = offset;
25
int cluster_size;
21
offset += s->offset;
26
- int cluster_sectors;
22
- return bdrv_co_truncate(bs->file, offset, exact, prealloc, 0, errp);
27
int l2_bits;
23
+ return bdrv_co_truncate(bs->file, offset, exact, prealloc, flags, errp);
28
int l2_size;
29
unsigned int l1_size;
30
@@ -XXX,XX +XXX,XX @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags,
31
}
32
s->cluster_bits = header.cluster_bits;
33
s->cluster_size = 1 << s->cluster_bits;
34
- s->cluster_sectors = 1 << (s->cluster_bits - 9);
35
s->l2_bits = header.l2_bits;
36
s->l2_size = 1 << s->l2_bits;
37
bs->total_sectors = header.size / 512;
38
@@ -XXX,XX +XXX,XX @@ static int decompress_cluster(BlockDriverState *bs, uint64_t cluster_offset)
39
return 0;
40
}
24
}
41
25
42
-static coroutine_fn int qcow_co_readv(BlockDriverState *bs, int64_t sector_num,
26
static void raw_eject(BlockDriverState *bs, bool eject_flag)
43
- int nb_sectors, QEMUIOVector *qiov)
27
@@ -XXX,XX +XXX,XX @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags,
44
+static void qcow_refresh_limits(BlockDriverState *bs, Error **errp)
28
bs->supported_zero_flags = BDRV_REQ_WRITE_UNCHANGED |
45
+{
29
((BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK) &
46
+ /* At least encrypted images require 512-byte alignment. Apply the
30
bs->file->bs->supported_zero_flags);
47
+ * limit universally, rather than just on encrypted images, as
31
+ bs->supported_truncate_flags = bs->file->bs->supported_truncate_flags &
48
+ * it's easier to let the block layer handle rounding than to
32
+ BDRV_REQ_ZERO_WRITE;
49
+ * audit this code further. */
33
50
+ bs->bl.request_alignment = BDRV_SECTOR_SIZE;
34
if (bs->probed && !bdrv_is_read_only(bs)) {
51
+}
35
bdrv_refresh_filename(bs->file->bs);
52
+
53
+static coroutine_fn int qcow_co_preadv(BlockDriverState *bs, uint64_t offset,
54
+ uint64_t bytes, QEMUIOVector *qiov,
55
+ int flags)
56
{
57
BDRVQcowState *s = bs->opaque;
58
int offset_in_cluster;
59
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow_co_readv(BlockDriverState *bs, int64_t sector_num,
60
QEMUIOVector hd_qiov;
61
uint8_t *buf;
62
void *orig_buf;
63
- int64_t offset = sector_num * BDRV_SECTOR_SIZE;
64
- int64_t bytes = nb_sectors * BDRV_SECTOR_SIZE;
65
66
+ assert(!flags);
67
if (qiov->niov > 1) {
68
buf = orig_buf = qemu_try_blockalign(bs, qiov->size);
69
if (buf == NULL) {
70
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow_co_readv(BlockDriverState *bs, int64_t sector_num,
71
return ret;
72
}
73
74
-static coroutine_fn int qcow_co_writev(BlockDriverState *bs, int64_t sector_num,
75
- int nb_sectors, QEMUIOVector *qiov,
76
- int flags)
77
+static coroutine_fn int qcow_co_pwritev(BlockDriverState *bs, uint64_t offset,
78
+ uint64_t bytes, QEMUIOVector *qiov,
79
+ int flags)
80
{
81
BDRVQcowState *s = bs->opaque;
82
int offset_in_cluster;
83
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow_co_writev(BlockDriverState *bs, int64_t sector_num,
84
QEMUIOVector hd_qiov;
85
uint8_t *buf;
86
void *orig_buf;
87
- int64_t offset = sector_num * BDRV_SECTOR_SIZE;
88
- int64_t bytes = nb_sectors * BDRV_SECTOR_SIZE;
89
90
assert(!flags);
91
s->cluster_cache_offset = -1; /* disable compressed cache */
92
@@ -XXX,XX +XXX,XX @@ qcow_co_pwritev_compressed(BlockDriverState *bs, uint64_t offset,
93
94
if (ret != Z_STREAM_END || out_len >= s->cluster_size) {
95
/* could not compress: write normal cluster */
96
- ret = qcow_co_writev(bs, offset >> BDRV_SECTOR_BITS,
97
- bytes >> BDRV_SECTOR_BITS, qiov, 0);
98
+ ret = qcow_co_pwritev(bs, offset, bytes, qiov, 0);
99
if (ret < 0) {
100
goto fail;
101
}
102
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_qcow = {
103
.bdrv_co_create_opts = qcow_co_create_opts,
104
.bdrv_has_zero_init = bdrv_has_zero_init_1,
105
.supports_backing = true,
106
+ .bdrv_refresh_limits = qcow_refresh_limits,
107
108
- .bdrv_co_readv = qcow_co_readv,
109
- .bdrv_co_writev = qcow_co_writev,
110
+ .bdrv_co_preadv = qcow_co_preadv,
111
+ .bdrv_co_pwritev = qcow_co_pwritev,
112
.bdrv_co_block_status = qcow_co_block_status,
113
114
.bdrv_make_empty = qcow_make_empty,
115
--
36
--
116
2.13.6
37
2.25.3
117
38
118
39
diff view generated by jsdifflib
1
From: Fam Zheng <famz@redhat.com>
1
For regular files, we always get BDRV_REQ_ZERO_WRITE behaviour from the
2
OS, so we can advertise the flag and just ignore it.
2
3
3
EINTR should be checked against errno, not ret. While fixing the bug,
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
collect the branches with a switch block.
5
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
5
6
Reviewed-by: Alberto Garcia <berto@igalia.com>
6
Also, change the return value from -ENOSTUP to -ENOSPC when the actual
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
7
issue is request range passes EOF, which should be distinguishable from
8
Message-Id: <20200424125448.63318-7-kwolf@redhat.com>
8
the case of error == ENOSYS by the caller, so that it could still retry
9
with other byte ranges, whereas it shouldn't retry anymore upon ENOSYS.
10
11
Signed-off-by: Fam Zheng <famz@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
---
10
---
14
block/file-posix.c | 17 +++++++++--------
11
block/file-posix.c | 4 ++++
15
1 file changed, 9 insertions(+), 8 deletions(-)
12
1 file changed, 4 insertions(+)
16
13
17
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
18
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
19
--- a/block/file-posix.c
16
--- a/block/file-posix.c
20
+++ b/block/file-posix.c
17
+++ b/block/file-posix.c
21
@@ -XXX,XX +XXX,XX @@ static ssize_t handle_aiocb_copy_range(RawPosixAIOData *aiocb)
18
@@ -XXX,XX +XXX,XX @@ static int raw_open_common(BlockDriverState *bs, QDict *options,
22
ssize_t ret = copy_file_range(aiocb->aio_fildes, &in_off,
19
#endif
23
aiocb->aio_fd2, &out_off,
20
24
bytes, 0);
21
bs->supported_zero_flags = BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK;
25
- if (ret == -EINTR) {
22
+ if (S_ISREG(st.st_mode)) {
26
- continue;
23
+ /* When extending regular files, we get zeros from the OS */
27
+ if (ret == 0) {
24
+ bs->supported_truncate_flags = BDRV_REQ_ZERO_WRITE;
28
+ /* No progress (e.g. when beyond EOF), let the caller fall back to
25
+ }
29
+ * buffer I/O. */
26
ret = 0;
30
+ return -ENOSPC;
27
fail:
31
}
28
if (filename && (bdrv_flags & BDRV_O_TEMPORARY)) {
32
if (ret < 0) {
33
- if (errno == ENOSYS) {
34
+ switch (errno) {
35
+ case ENOSYS:
36
return -ENOTSUP;
37
- } else {
38
+ case EINTR:
39
+ continue;
40
+ default:
41
return -errno;
42
}
43
}
44
- if (!ret) {
45
- /* No progress (e.g. when beyond EOF), fall back to buffer I/O. */
46
- return -ENOTSUP;
47
- }
48
bytes -= ret;
49
}
50
return 0;
51
--
29
--
52
2.13.6
30
2.25.3
53
31
54
32
diff view generated by jsdifflib
1
When growing an image, block drivers (especially protocol drivers) may
1
When extending the size of an image that has a backing file larger than
2
initialise the newly added area. I/O requests to the same area need to
2
its old size, make sure that the backing file data doesn't become
3
wait for this initialisation to be completed so that data writes don't
3
visible in the guest, but the added area is properly zeroed out.
4
get overwritten and reads don't read uninitialised data.
5
4
6
To avoid overhead in the fast I/O path by adding new locking in the
5
Consider the following scenario where the overlay is shorter than its
7
protocol drivers and to restrict the impact to requests that actually
6
backing file:
8
touch the new area, reuse the existing tracked request infrastructure in
9
block/io.c and mark all discard requests as serialising.
10
7
11
With this change, it is safe for protocol drivers to make
8
base.qcow2: AAAAAAAA
12
.bdrv_co_truncate actually asynchronous.
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.
13
29
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
30
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
Reviewed-by: Stefan Hajnoczi <stefanha@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>
34
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
16
---
35
---
17
include/block/block_int.h | 1 +
36
block/io.c | 25 +++++++++++++++++++++++++
18
block/io.c | 25 +++++++++++++++++++++++++
37
1 file changed, 25 insertions(+)
19
2 files changed, 26 insertions(+)
20
38
21
diff --git a/include/block/block_int.h b/include/block/block_int.h
22
index XXXXXXX..XXXXXXX 100644
23
--- a/include/block/block_int.h
24
+++ b/include/block/block_int.h
25
@@ -XXX,XX +XXX,XX @@ enum BdrvTrackedRequestType {
26
BDRV_TRACKED_READ,
27
BDRV_TRACKED_WRITE,
28
BDRV_TRACKED_DISCARD,
29
+ BDRV_TRACKED_TRUNCATE,
30
};
31
32
typedef struct BdrvTrackedRequest {
33
diff --git a/block/io.c b/block/io.c
39
diff --git a/block/io.c b/block/io.c
34
index XXXXXXX..XXXXXXX 100644
40
index XXXXXXX..XXXXXXX 100644
35
--- a/block/io.c
41
--- a/block/io.c
36
+++ b/block/io.c
42
+++ b/block/io.c
37
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset,
43
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
38
{
44
goto out;
39
BlockDriverState *bs = child->bs;
40
BlockDriver *drv = bs->drv;
41
+ BdrvTrackedRequest req;
42
+ int64_t old_size, new_bytes;
43
int ret;
44
45
assert(child->perm & BLK_PERM_RESIZE);
46
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset,
47
return -EINVAL;
48
}
45
}
49
46
50
+ old_size = bdrv_getlength(bs);
47
+ /*
51
+ if (old_size < 0) {
48
+ * If the image has a backing file that is large enough that it would
52
+ error_setg_errno(errp, -old_size, "Failed to get old image size");
49
+ * provide data for the new area, we cannot leave it unallocated because
53
+ return old_size;
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
+ }
54
+ }
70
+ }
55
+
71
+
56
+ if (offset > old_size) {
72
if (drv->bdrv_co_truncate) {
57
+ new_bytes = offset - old_size;
73
if (flags & ~bs->supported_truncate_flags) {
58
+ } else {
74
error_setg(errp, "Block driver does not support requested flags");
59
+ new_bytes = 0;
60
+ }
61
+
62
bdrv_inc_in_flight(bs);
63
+ tracked_request_begin(&req, bs, offset, new_bytes, BDRV_TRACKED_TRUNCATE);
64
+
65
+ /* If we are growing the image and potentially using preallocation for the
66
+ * new area, we need to make sure that no write requests are made to it
67
+ * concurrently or they might be overwritten by preallocation. */
68
+ if (new_bytes) {
69
+ mark_request_serialising(&req, 1);
70
+ wait_serialising_requests(&req);
71
+ }
72
73
if (!drv->bdrv_co_truncate) {
74
if (bs->file && drv->is_filter) {
75
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset,
76
atomic_inc(&bs->write_gen);
77
78
out:
79
+ tracked_request_end(&req);
80
bdrv_dec_in_flight(bs);
81
+
82
return ret;
83
}
84
85
--
75
--
86
2.13.6
76
2.25.3
87
77
88
78
diff view generated by jsdifflib
1
This adds a test for a temporary write failure, which simulates the
1
We want to keep TEST_IMG for the full path of the main test image, but
2
situation after werror=stop/enospc has stopped the VM. We shouldn't
2
filter_testfiles() must be called for other test images before replacing
3
leave leaked clusters behind in such cases.
3
other things like the image format because the test directory path could
4
contain the format as a substring.
5
6
Insert a filter_testfiles() call between both.
4
7
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
Reviewed-by: Max Reitz <mreitz@redhat.com>
9
Reviewed-by: Max Reitz <mreitz@redhat.com>
10
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
11
Message-Id: <20200424125448.63318-9-kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
---
13
---
8
tests/qemu-iotests/026 | 17 +++++++++++++++++
14
tests/qemu-iotests/iotests.py | 5 +++--
9
tests/qemu-iotests/026.out | 8 ++++++++
15
1 file changed, 3 insertions(+), 2 deletions(-)
10
tests/qemu-iotests/026.out.nocache | 8 ++++++++
11
3 files changed, 33 insertions(+)
12
16
13
diff --git a/tests/qemu-iotests/026 b/tests/qemu-iotests/026
17
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
14
index XXXXXXX..XXXXXXX 100755
15
--- a/tests/qemu-iotests/026
16
+++ b/tests/qemu-iotests/026
17
@@ -XXX,XX +XXX,XX @@ done
18
done
19
done
20
21
+echo
22
+echo === Avoid cluster leaks after temporary failure ===
23
+echo
24
+
25
+cat > "$TEST_DIR/blkdebug.conf" <<EOF
26
+[inject-error]
27
+event = "write_aio"
28
+errno = "5"
29
+once = "on"
30
+EOF
31
+
32
+# After the failed first write, do a second write so that the updated refcount
33
+# block is actually written back
34
+_make_test_img 64M
35
+$QEMU_IO -c "write 0 1M" -c "write 0 1M" "$BLKDBG_TEST_IMG" | _filter_qemu_io
36
+_check_test_img
37
+
38
# success, all done
39
echo "*** done"
40
rm -f $seq.full
41
diff --git a/tests/qemu-iotests/026.out b/tests/qemu-iotests/026.out
42
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
43
--- a/tests/qemu-iotests/026.out
19
--- a/tests/qemu-iotests/iotests.py
44
+++ b/tests/qemu-iotests/026.out
20
+++ b/tests/qemu-iotests/iotests.py
45
@@ -XXX,XX +XXX,XX @@ write failed: No space left on device
21
@@ -XXX,XX +XXX,XX @@ def filter_img_info(output, filename):
46
22
for line in output.split('\n'):
47
96 leaked clusters were found on the image.
23
if 'disk size' in line or 'actual-size' in line:
48
This means waste of disk space, but no harm to data.
24
continue
49
+
25
- line = line.replace(filename, 'TEST_IMG') \
50
+=== Avoid cluster leaks after temporary failure ===
26
- .replace(imgfmt, 'IMGFMT')
51
+
27
+ line = line.replace(filename, 'TEST_IMG')
52
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
28
+ line = filter_testfiles(line)
53
+write failed: Input/output error
29
+ line = line.replace(imgfmt, 'IMGFMT')
54
+wrote 1048576/1048576 bytes at offset 0
30
line = re.sub('iters: [0-9]+', 'iters: XXX', line)
55
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
31
line = re.sub('uuid: [-a-f0-9]+', 'uuid: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX', line)
56
+No errors were found on the image.
32
line = re.sub('cid: [0-9]+', 'cid: XXXXXXXXXX', line)
57
*** done
58
diff --git a/tests/qemu-iotests/026.out.nocache b/tests/qemu-iotests/026.out.nocache
59
index XXXXXXX..XXXXXXX 100644
60
--- a/tests/qemu-iotests/026.out.nocache
61
+++ b/tests/qemu-iotests/026.out.nocache
62
@@ -XXX,XX +XXX,XX @@ write failed: No space left on device
63
64
96 leaked clusters were found on the image.
65
This means waste of disk space, but no harm to data.
66
+
67
+=== Avoid cluster leaks after temporary failure ===
68
+
69
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
70
+write failed: Input/output error
71
+wrote 1048576/1048576 bytes at offset 0
72
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
73
+No errors were found on the image.
74
*** done
75
--
33
--
76
2.13.6
34
2.25.3
77
35
78
36
diff view generated by jsdifflib
1
From: Markus Armbruster <armbru@redhat.com>
1
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2
2
Message-Id: <20200424125448.63318-10-kwolf@redhat.com>
3
Coverity can't see that qobject_input_visitor_new_flat_confused()
3
Reviewed-by: Max Reitz <mreitz@redhat.com>
4
returns non-null when it doesn't set @local_err. Check the return
4
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
5
value instead, like all the other callers do.
6
7
Fixes: CID 1393615
8
Fixes: CID 1393616
9
Signed-off-by: Markus Armbruster <armbru@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
---
6
---
12
block/crypto.c | 4 ++--
7
tests/qemu-iotests/274 | 155 +++++++++++++++++++++
13
1 file changed, 2 insertions(+), 2 deletions(-)
8
tests/qemu-iotests/274.out | 268 +++++++++++++++++++++++++++++++++++++
9
tests/qemu-iotests/group | 1 +
10
3 files changed, 424 insertions(+)
11
create mode 100755 tests/qemu-iotests/274
12
create mode 100644 tests/qemu-iotests/274.out
14
13
15
diff --git a/block/crypto.c b/block/crypto.c
14
diff --git a/tests/qemu-iotests/274 b/tests/qemu-iotests/274
15
new file mode 100755
16
index XXXXXXX..XXXXXXX
17
--- /dev/null
18
+++ b/tests/qemu-iotests/274
19
@@ -XXX,XX +XXX,XX @@
20
+#!/usr/bin/env python3
21
+#
22
+# Copyright (C) 2019 Red Hat, Inc.
23
+#
24
+# This program is free software; you can redistribute it and/or modify
25
+# it under the terms of the GNU General Public License as published by
26
+# the Free Software Foundation; either version 2 of the License, or
27
+# (at your option) any later version.
28
+#
29
+# This program is distributed in the hope that it will be useful,
30
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
31
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
32
+# GNU General Public License for more details.
33
+#
34
+# You should have received a copy of the GNU General Public License
35
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
36
+#
37
+# Creator/Owner: Kevin Wolf <kwolf@redhat.com>
38
+#
39
+# Some tests for short backing files and short overlays
40
+
41
+import iotests
42
+
43
+iotests.verify_image_format(supported_fmts=['qcow2'])
44
+iotests.verify_platform(['linux'])
45
+
46
+size_short = 1 * 1024 * 1024
47
+size_long = 2 * 1024 * 1024
48
+size_diff = size_long - size_short
49
+
50
+def create_chain() -> None:
51
+ iotests.qemu_img_log('create', '-f', iotests.imgfmt, base,
52
+ str(size_long))
53
+ iotests.qemu_img_log('create', '-f', iotests.imgfmt, '-b', base, mid,
54
+ str(size_short))
55
+ iotests.qemu_img_log('create', '-f', iotests.imgfmt, '-b', mid, top,
56
+ str(size_long))
57
+
58
+ iotests.qemu_io_log('-c', 'write -P 1 0 %d' % size_long, base)
59
+
60
+def create_vm() -> iotests.VM:
61
+ vm = iotests.VM()
62
+ vm.add_blockdev('file,filename=%s,node-name=base-file' % base)
63
+ vm.add_blockdev('%s,file=base-file,node-name=base' % iotests.imgfmt)
64
+ vm.add_blockdev('file,filename=%s,node-name=mid-file' % mid)
65
+ vm.add_blockdev('%s,file=mid-file,node-name=mid,backing=base'
66
+ % iotests.imgfmt)
67
+ vm.add_drive(top, 'backing=mid,node-name=top')
68
+ return vm
69
+
70
+with iotests.FilePath('base') as base, \
71
+ iotests.FilePath('mid') as mid, \
72
+ iotests.FilePath('top') as top:
73
+
74
+ iotests.log('== Commit tests ==')
75
+
76
+ create_chain()
77
+
78
+ iotests.log('=== Check visible data ===')
79
+
80
+ iotests.qemu_io_log('-c', 'read -P 1 0 %d' % size_short, top)
81
+ iotests.qemu_io_log('-c', 'read -P 0 %d %d' % (size_short, size_diff), top)
82
+
83
+ iotests.log('=== Checking allocation status ===')
84
+
85
+ iotests.qemu_io_log('-c', 'alloc 0 %d' % size_short,
86
+ '-c', 'alloc %d %d' % (size_short, size_diff),
87
+ base)
88
+
89
+ iotests.qemu_io_log('-c', 'alloc 0 %d' % size_short,
90
+ '-c', 'alloc %d %d' % (size_short, size_diff),
91
+ mid)
92
+
93
+ iotests.qemu_io_log('-c', 'alloc 0 %d' % size_short,
94
+ '-c', 'alloc %d %d' % (size_short, size_diff),
95
+ top)
96
+
97
+ iotests.log('=== Checking map ===')
98
+
99
+ iotests.qemu_img_log('map', '--output=json', base)
100
+ iotests.qemu_img_log('map', '--output=human', base)
101
+ iotests.qemu_img_log('map', '--output=json', mid)
102
+ iotests.qemu_img_log('map', '--output=human', mid)
103
+ iotests.qemu_img_log('map', '--output=json', top)
104
+ iotests.qemu_img_log('map', '--output=human', top)
105
+
106
+ iotests.log('=== Testing qemu-img commit (top -> mid) ===')
107
+
108
+ iotests.qemu_img_log('commit', top)
109
+ iotests.img_info_log(mid)
110
+ iotests.qemu_io_log('-c', 'read -P 1 0 %d' % size_short, mid)
111
+ iotests.qemu_io_log('-c', 'read -P 0 %d %d' % (size_short, size_diff), mid)
112
+
113
+ iotests.log('=== Testing HMP commit (top -> mid) ===')
114
+
115
+ create_chain()
116
+ with create_vm() as vm:
117
+ vm.launch()
118
+ vm.qmp_log('human-monitor-command', command_line='commit drive0')
119
+
120
+ iotests.img_info_log(mid)
121
+ iotests.qemu_io_log('-c', 'read -P 1 0 %d' % size_short, mid)
122
+ iotests.qemu_io_log('-c', 'read -P 0 %d %d' % (size_short, size_diff), mid)
123
+
124
+ iotests.log('=== Testing QMP active commit (top -> mid) ===')
125
+
126
+ create_chain()
127
+ with create_vm() as vm:
128
+ vm.launch()
129
+ vm.qmp_log('block-commit', device='top', base_node='mid',
130
+ job_id='job0', auto_dismiss=False)
131
+ vm.run_job('job0', wait=5)
132
+
133
+ iotests.img_info_log(mid)
134
+ iotests.qemu_io_log('-c', 'read -P 1 0 %d' % size_short, mid)
135
+ iotests.qemu_io_log('-c', 'read -P 0 %d %d' % (size_short, size_diff), mid)
136
+
137
+
138
+ iotests.log('== Resize tests ==')
139
+
140
+ # Use different sizes for different allocation modes:
141
+ #
142
+ # We want to have at least one test where 32 bit truncation in the size of
143
+ # the overlapping area becomes visible. This is covered by the
144
+ # prealloc='off' case (1G to 6G is an overlap of 5G).
145
+ #
146
+ # However, we can only do this for modes that don't preallocate data
147
+ # because otherwise we might run out of space on the test host.
148
+ #
149
+ # We also want to test some unaligned combinations.
150
+ for (prealloc, base_size, top_size_old, top_size_new, off) in [
151
+ ('off', '6G', '1G', '8G', '5G'),
152
+ ('metadata', '32G', '30G', '33G', '31G'),
153
+ ('falloc', '10M', '5M', '15M', '9M'),
154
+ ('full', '16M', '8M', '12M', '11M'),
155
+ ('off', '384k', '253k', '512k', '253k'),
156
+ ('off', '400k', '256k', '512k', '336k'),
157
+ ('off', '512k', '256k', '500k', '436k')]:
158
+
159
+ iotests.log('=== preallocation=%s ===' % prealloc)
160
+ iotests.qemu_img_log('create', '-f', iotests.imgfmt, base, base_size)
161
+ iotests.qemu_img_log('create', '-f', iotests.imgfmt, '-b', base, top,
162
+ top_size_old)
163
+ iotests.qemu_io_log('-c', 'write -P 1 %s 64k' % off, base)
164
+
165
+ # After this, top_size_old to base_size should be allocated/zeroed.
166
+ #
167
+ # In theory, leaving base_size to top_size_new unallocated would be
168
+ # correct, but in practice, if we zero out anything, we zero out
169
+ # everything up to top_size_new.
170
+ iotests.qemu_img_log('resize', '-f', iotests.imgfmt,
171
+ '--preallocation', prealloc, top, top_size_new)
172
+ iotests.qemu_io_log('-c', 'read -P 0 %s 64k' % off, top)
173
+ iotests.qemu_io_log('-c', 'map', top)
174
+ iotests.qemu_img_log('map', '--output=json', top)
175
diff --git a/tests/qemu-iotests/274.out b/tests/qemu-iotests/274.out
176
new file mode 100644
177
index XXXXXXX..XXXXXXX
178
--- /dev/null
179
+++ b/tests/qemu-iotests/274.out
180
@@ -XXX,XX +XXX,XX @@
181
+== Commit tests ==
182
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=2097152 cluster_size=65536 lazy_refcounts=off refcount_bits=16
183
+
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
185
+
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
187
+
188
+wrote 2097152/2097152 bytes at offset 0
189
+2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
190
+
191
+=== Check visible data ===
192
+read 1048576/1048576 bytes at offset 0
193
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
194
+
195
+read 1048576/1048576 bytes at offset 1048576
196
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
197
+
198
+=== Checking allocation status ===
199
+1048576/1048576 bytes allocated at offset 0 bytes
200
+1048576/1048576 bytes allocated at offset 1 MiB
201
+
202
+0/1048576 bytes allocated at offset 0 bytes
203
+0/0 bytes allocated at offset 1 MiB
204
+
205
+0/1048576 bytes allocated at offset 0 bytes
206
+0/1048576 bytes allocated at offset 1 MiB
207
+
208
+=== Checking map ===
209
+[{ "start": 0, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": 327680}]
210
+
211
+Offset Length Mapped to File
212
+0 0x200000 0x50000 TEST_DIR/PID-base
213
+
214
+[{ "start": 0, "length": 1048576, "depth": 1, "zero": false, "data": true, "offset": 327680}]
215
+
216
+Offset Length Mapped to File
217
+0 0x100000 0x50000 TEST_DIR/PID-base
218
+
219
+[{ "start": 0, "length": 1048576, "depth": 2, "zero": false, "data": true, "offset": 327680},
220
+{ "start": 1048576, "length": 1048576, "depth": 0, "zero": true, "data": false}]
221
+
222
+Offset Length Mapped to File
223
+0 0x100000 0x50000 TEST_DIR/PID-base
224
+
225
+=== Testing qemu-img commit (top -> mid) ===
226
+Image committed.
227
+
228
+image: TEST_IMG
229
+file format: IMGFMT
230
+virtual size: 2 MiB (2097152 bytes)
231
+cluster_size: 65536
232
+backing file: TEST_DIR/PID-base
233
+Format specific information:
234
+ compat: 1.1
235
+ lazy refcounts: false
236
+ refcount bits: 16
237
+ corrupt: false
238
+
239
+read 1048576/1048576 bytes at offset 0
240
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
241
+
242
+read 1048576/1048576 bytes at offset 1048576
243
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
244
+
245
+=== Testing HMP commit (top -> mid) ===
246
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=2097152 cluster_size=65536 lazy_refcounts=off refcount_bits=16
247
+
248
+Formatting 'TEST_DIR/PID-mid', fmt=qcow2 size=1048576 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
249
+
250
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=2097152 backing_file=TEST_DIR/PID-mid cluster_size=65536 lazy_refcounts=off refcount_bits=16
251
+
252
+wrote 2097152/2097152 bytes at offset 0
253
+2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
254
+
255
+{"execute": "human-monitor-command", "arguments": {"command-line": "commit drive0"}}
256
+{"return": ""}
257
+image: TEST_IMG
258
+file format: IMGFMT
259
+virtual size: 2 MiB (2097152 bytes)
260
+cluster_size: 65536
261
+backing file: TEST_DIR/PID-base
262
+Format specific information:
263
+ compat: 1.1
264
+ lazy refcounts: false
265
+ refcount bits: 16
266
+ corrupt: false
267
+
268
+read 1048576/1048576 bytes at offset 0
269
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
270
+
271
+read 1048576/1048576 bytes at offset 1048576
272
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
273
+
274
+=== Testing QMP active commit (top -> mid) ===
275
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=2097152 cluster_size=65536 lazy_refcounts=off refcount_bits=16
276
+
277
+Formatting 'TEST_DIR/PID-mid', fmt=qcow2 size=1048576 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
278
+
279
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=2097152 backing_file=TEST_DIR/PID-mid cluster_size=65536 lazy_refcounts=off refcount_bits=16
280
+
281
+wrote 2097152/2097152 bytes at offset 0
282
+2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
283
+
284
+{"execute": "block-commit", "arguments": {"auto-dismiss": false, "base-node": "mid", "device": "top", "job-id": "job0"}}
285
+{"return": {}}
286
+{"execute": "job-complete", "arguments": {"id": "job0"}}
287
+{"return": {}}
288
+{"data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "commit"}, "event": "BLOCK_JOB_READY", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
289
+{"data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "commit"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
290
+{"execute": "job-dismiss", "arguments": {"id": "job0"}}
291
+{"return": {}}
292
+image: TEST_IMG
293
+file format: IMGFMT
294
+virtual size: 2 MiB (2097152 bytes)
295
+cluster_size: 65536
296
+backing file: TEST_DIR/PID-base
297
+Format specific information:
298
+ compat: 1.1
299
+ lazy refcounts: false
300
+ refcount bits: 16
301
+ corrupt: false
302
+
303
+read 1048576/1048576 bytes at offset 0
304
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
305
+
306
+read 1048576/1048576 bytes at offset 1048576
307
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
308
+
309
+== Resize tests ==
310
+=== preallocation=off ===
311
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=6442450944 cluster_size=65536 lazy_refcounts=off refcount_bits=16
312
+
313
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=1073741824 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
314
+
315
+wrote 65536/65536 bytes at offset 5368709120
316
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
317
+
318
+Image resized.
319
+
320
+read 65536/65536 bytes at offset 5368709120
321
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
322
+
323
+1 GiB (0x40000000) bytes not allocated at offset 0 bytes (0x0)
324
+7 GiB (0x1c0000000) bytes allocated at offset 1 GiB (0x40000000)
325
+
326
+[{ "start": 0, "length": 1073741824, "depth": 1, "zero": true, "data": false},
327
+{ "start": 1073741824, "length": 7516192768, "depth": 0, "zero": true, "data": false}]
328
+
329
+=== preallocation=metadata ===
330
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=34359738368 cluster_size=65536 lazy_refcounts=off refcount_bits=16
331
+
332
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=32212254720 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
333
+
334
+wrote 65536/65536 bytes at offset 33285996544
335
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
336
+
337
+Image resized.
338
+
339
+read 65536/65536 bytes at offset 33285996544
340
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
341
+
342
+30 GiB (0x780000000) bytes not allocated at offset 0 bytes (0x0)
343
+3 GiB (0xc0000000) bytes allocated at offset 30 GiB (0x780000000)
344
+
345
+[{ "start": 0, "length": 32212254720, "depth": 1, "zero": true, "data": false},
346
+{ "start": 32212254720, "length": 536870912, "depth": 0, "zero": true, "data": false, "offset": 327680},
347
+{ "start": 32749125632, "length": 536870912, "depth": 0, "zero": true, "data": false, "offset": 537264128},
348
+{ "start": 33285996544, "length": 536870912, "depth": 0, "zero": true, "data": false, "offset": 1074200576},
349
+{ "start": 33822867456, "length": 536870912, "depth": 0, "zero": true, "data": false, "offset": 1611137024},
350
+{ "start": 34359738368, "length": 536870912, "depth": 0, "zero": true, "data": false, "offset": 2148139008},
351
+{ "start": 34896609280, "length": 536870912, "depth": 0, "zero": true, "data": false, "offset": 2685075456}]
352
+
353
+=== preallocation=falloc ===
354
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=10485760 cluster_size=65536 lazy_refcounts=off refcount_bits=16
355
+
356
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=5242880 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
357
+
358
+wrote 65536/65536 bytes at offset 9437184
359
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
360
+
361
+Image resized.
362
+
363
+read 65536/65536 bytes at offset 9437184
364
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
365
+
366
+5 MiB (0x500000) bytes not allocated at offset 0 bytes (0x0)
367
+10 MiB (0xa00000) bytes allocated at offset 5 MiB (0x500000)
368
+
369
+[{ "start": 0, "length": 5242880, "depth": 1, "zero": true, "data": false},
370
+{ "start": 5242880, "length": 10485760, "depth": 0, "zero": true, "data": false, "offset": 327680}]
371
+
372
+=== preallocation=full ===
373
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=16777216 cluster_size=65536 lazy_refcounts=off refcount_bits=16
374
+
375
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=8388608 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
376
+
377
+wrote 65536/65536 bytes at offset 11534336
378
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
379
+
380
+Image resized.
381
+
382
+read 65536/65536 bytes at offset 11534336
383
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
384
+
385
+8 MiB (0x800000) bytes not allocated at offset 0 bytes (0x0)
386
+4 MiB (0x400000) bytes allocated at offset 8 MiB (0x800000)
387
+
388
+[{ "start": 0, "length": 8388608, "depth": 1, "zero": true, "data": false},
389
+{ "start": 8388608, "length": 4194304, "depth": 0, "zero": true, "data": false, "offset": 327680}]
390
+
391
+=== preallocation=off ===
392
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=393216 cluster_size=65536 lazy_refcounts=off refcount_bits=16
393
+
394
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=259072 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
395
+
396
+wrote 65536/65536 bytes at offset 259072
397
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
398
+
399
+Image resized.
400
+
401
+read 65536/65536 bytes at offset 259072
402
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
403
+
404
+192 KiB (0x30000) bytes not allocated at offset 0 bytes (0x0)
405
+320 KiB (0x50000) bytes allocated at offset 192 KiB (0x30000)
406
+
407
+[{ "start": 0, "length": 196608, "depth": 1, "zero": true, "data": false},
408
+{ "start": 196608, "length": 65536, "depth": 0, "zero": false, "data": true, "offset": 327680},
409
+{ "start": 262144, "length": 262144, "depth": 0, "zero": true, "data": false}]
410
+
411
+=== preallocation=off ===
412
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=409600 cluster_size=65536 lazy_refcounts=off refcount_bits=16
413
+
414
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=262144 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
415
+
416
+wrote 65536/65536 bytes at offset 344064
417
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
418
+
419
+Image resized.
420
+
421
+read 65536/65536 bytes at offset 344064
422
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
423
+
424
+256 KiB (0x40000) bytes not allocated at offset 0 bytes (0x0)
425
+256 KiB (0x40000) bytes allocated at offset 256 KiB (0x40000)
426
+
427
+[{ "start": 0, "length": 262144, "depth": 1, "zero": true, "data": false},
428
+{ "start": 262144, "length": 262144, "depth": 0, "zero": true, "data": false}]
429
+
430
+=== preallocation=off ===
431
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=524288 cluster_size=65536 lazy_refcounts=off refcount_bits=16
432
+
433
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=262144 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
434
+
435
+wrote 65536/65536 bytes at offset 446464
436
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
437
+
438
+Image resized.
439
+
440
+read 65536/65536 bytes at offset 446464
441
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
442
+
443
+256 KiB (0x40000) bytes not allocated at offset 0 bytes (0x0)
444
+244 KiB (0x3d000) bytes allocated at offset 256 KiB (0x40000)
445
+
446
+[{ "start": 0, "length": 262144, "depth": 1, "zero": true, "data": false},
447
+{ "start": 262144, "length": 249856, "depth": 0, "zero": true, "data": false}]
448
+
449
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
16
index XXXXXXX..XXXXXXX 100644
450
index XXXXXXX..XXXXXXX 100644
17
--- a/block/crypto.c
451
--- a/tests/qemu-iotests/group
18
+++ b/block/crypto.c
452
+++ b/tests/qemu-iotests/group
19
@@ -XXX,XX +XXX,XX @@ block_crypto_open_opts_init(QCryptoBlockFormat format,
453
@@ -XXX,XX +XXX,XX @@
20
ret->format = format;
454
270 rw backing quick
21
455
272 rw
22
v = qobject_input_visitor_new_flat_confused(opts, &local_err);
456
273 backing quick
23
- if (local_err) {
457
+274 rw backing
24
+ if (!v) {
458
277 rw quick
25
goto out;
459
279 rw backing quick
26
}
460
280 rw migration quick
27
28
@@ -XXX,XX +XXX,XX @@ block_crypto_create_opts_init(QCryptoBlockFormat format,
29
ret->format = format;
30
31
v = qobject_input_visitor_new_flat_confused(opts, &local_err);
32
- if (local_err) {
33
+ if (!v) {
34
goto out;
35
}
36
37
--
461
--
38
2.13.6
462
2.25.3
39
463
40
464
diff view generated by jsdifflib
Deleted patch
1
Commit 51f63ec7d tried to change all references to 2.13 into 3.0, but
2
it failed to achieve this because it was not properly rebased on top of
3
the series introducing qapi/job.json. Change the references now.
4
1
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
Reviewed-by: Markus Armbruster <armbru@redhat.com>
7
Reviewed-by: Eric Blake <eblake@redhat.com>
8
---
9
qapi/job.json | 18 +++++++++---------
10
1 file changed, 9 insertions(+), 9 deletions(-)
11
12
diff --git a/qapi/job.json b/qapi/job.json
13
index XXXXXXX..XXXXXXX 100644
14
--- a/qapi/job.json
15
+++ b/qapi/job.json
16
@@ -XXX,XX +XXX,XX @@
17
# @id: The job identifier
18
# @status: The new job status
19
#
20
-# Since: 2.13
21
+# Since: 3.0
22
##
23
{ 'event': 'JOB_STATUS_CHANGE',
24
'data': { 'id': 'str',
25
@@ -XXX,XX +XXX,XX @@
26
#
27
# @id: The job identifier.
28
#
29
-# Since: 2.13
30
+# Since: 3.0
31
##
32
{ 'command': 'job-pause', 'data': { 'id': 'str' } }
33
34
@@ -XXX,XX +XXX,XX @@
35
#
36
# @id : The job identifier.
37
#
38
-# Since: 2.13
39
+# Since: 3.0
40
##
41
{ 'command': 'job-resume', 'data': { 'id': 'str' } }
42
43
@@ -XXX,XX +XXX,XX @@
44
#
45
# @id: The job identifier.
46
#
47
-# Since: 2.13
48
+# Since: 3.0
49
##
50
{ 'command': 'job-cancel', 'data': { 'id': 'str' } }
51
52
@@ -XXX,XX +XXX,XX @@
53
#
54
# @id: The job identifier.
55
#
56
-# Since: 2.13
57
+# Since: 3.0
58
##
59
{ 'command': 'job-complete', 'data': { 'id': 'str' } }
60
61
@@ -XXX,XX +XXX,XX @@
62
#
63
# @id: The job identifier.
64
#
65
-# Since: 2.13
66
+# Since: 3.0
67
##
68
{ 'command': 'job-dismiss', 'data': { 'id': 'str' } }
69
70
@@ -XXX,XX +XXX,XX @@
71
# @id: The identifier of any job in the transaction, or of a job that is not
72
# part of any transaction.
73
#
74
-# Since: 2.13
75
+# Since: 3.0
76
##
77
{ 'command': 'job-finalize', 'data': { 'id': 'str' } }
78
79
@@ -XXX,XX +XXX,XX @@
80
# the reason for the job failure. It should not be parsed
81
# by applications.
82
#
83
-# Since: 2.13
84
+# Since: 3.0
85
##
86
{ 'struct': 'JobInfo',
87
'data': { 'id': 'str', 'type': 'JobType', 'status': 'JobStatus',
88
@@ -XXX,XX +XXX,XX @@
89
#
90
# Returns: a list with a @JobInfo for each active job
91
#
92
-# Since: 2.13
93
+# Since: 3.0
94
##
95
{ 'command': 'query-jobs', 'returns': ['JobInfo'] }
96
--
97
2.13.6
98
99
diff view generated by jsdifflib
Deleted patch
1
The error handling policy was traditionally set with -drive, but with
2
-blockdev it is no longer possible to set frontend options. scsi-disk
3
(and other block devices) have long supported qdev properties to
4
configure the error handling policy, so let's add these options to
5
usb-storage as well and just forward them to the internal scsi-disk
6
instance.
7
1
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Reviewed-by: Markus Armbruster <armbru@redhat.com>
10
---
11
include/hw/scsi/scsi.h | 2 ++
12
hw/scsi/scsi-bus.c | 11 ++++++++++-
13
hw/usb/dev-storage.c | 2 ++
14
3 files changed, 14 insertions(+), 1 deletion(-)
15
16
diff --git a/include/hw/scsi/scsi.h b/include/hw/scsi/scsi.h
17
index XXXXXXX..XXXXXXX 100644
18
--- a/include/hw/scsi/scsi.h
19
+++ b/include/hw/scsi/scsi.h
20
@@ -XXX,XX +XXX,XX @@ static inline SCSIBus *scsi_bus_from_device(SCSIDevice *d)
21
SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockBackend *blk,
22
int unit, bool removable, int bootindex,
23
bool share_rw,
24
+ BlockdevOnError rerror,
25
+ BlockdevOnError werror,
26
const char *serial, Error **errp);
27
void scsi_bus_legacy_handle_cmdline(SCSIBus *bus);
28
void scsi_legacy_handle_cmdline(void);
29
diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c
30
index XXXXXXX..XXXXXXX 100644
31
--- a/hw/scsi/scsi-bus.c
32
+++ b/hw/scsi/scsi-bus.c
33
@@ -XXX,XX +XXX,XX @@ static void scsi_qdev_unrealize(DeviceState *qdev, Error **errp)
34
SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockBackend *blk,
35
int unit, bool removable, int bootindex,
36
bool share_rw,
37
+ BlockdevOnError rerror,
38
+ BlockdevOnError werror,
39
const char *serial, Error **errp)
40
{
41
const char *driver;
42
@@ -XXX,XX +XXX,XX @@ SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockBackend *blk,
43
object_unparent(OBJECT(dev));
44
return NULL;
45
}
46
+
47
+ qdev_prop_set_enum(dev, "rerror", rerror);
48
+ qdev_prop_set_enum(dev, "werror", werror);
49
+
50
object_property_set_bool(OBJECT(dev), true, "realized", &err);
51
if (err != NULL) {
52
error_propagate(errp, err);
53
@@ -XXX,XX +XXX,XX @@ void scsi_bus_legacy_handle_cmdline(SCSIBus *bus)
54
}
55
qemu_opts_loc_restore(dinfo->opts);
56
scsi_bus_legacy_add_drive(bus, blk_by_legacy_dinfo(dinfo),
57
- unit, false, -1, false, NULL, &error_fatal);
58
+ unit, false, -1, false,
59
+ BLOCKDEV_ON_ERROR_AUTO,
60
+ BLOCKDEV_ON_ERROR_AUTO,
61
+ NULL, &error_fatal);
62
}
63
loc_pop(&loc);
64
}
65
diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c
66
index XXXXXXX..XXXXXXX 100644
67
--- a/hw/usb/dev-storage.c
68
+++ b/hw/usb/dev-storage.c
69
@@ -XXX,XX +XXX,XX @@ static void usb_msd_storage_realize(USBDevice *dev, Error **errp)
70
&usb_msd_scsi_info_storage, NULL);
71
scsi_dev = scsi_bus_legacy_add_drive(&s->bus, blk, 0, !!s->removable,
72
s->conf.bootindex, s->conf.share_rw,
73
+ s->conf.rerror, s->conf.werror,
74
dev->serial,
75
errp);
76
blk_unref(blk);
77
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_usb_msd = {
78
79
static Property msd_properties[] = {
80
DEFINE_BLOCK_PROPERTIES(MSDState, conf),
81
+ DEFINE_BLOCK_ERROR_PROPERTIES(MSDState, conf),
82
DEFINE_PROP_BIT("removable", MSDState, removable, 0, false),
83
DEFINE_PROP_END_OF_LIST(),
84
};
85
--
86
2.13.6
87
88
diff view generated by jsdifflib
1
From: Fam Zheng <famz@redhat.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
Not updating src_offset will result in wrong data being written to dst
7
Instead, try to forward the BDRV_REQ_ZERO_WRITE to the protocol driver,
4
image.
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.
5
10
6
Reported-by: Max Reitz <mreitz@redhat.com>
11
Unfortunately, the same approach doesn't work for metadata
7
Signed-off-by: Fam Zheng <famz@redhat.com>
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>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
18
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
19
---
10
block/qcow2.c | 1 +
20
block/qcow2.c | 22 +++++++++++++++++++---
11
tests/qemu-iotests/063 | 9 +++++++++
21
tests/qemu-iotests/274.out | 4 ++--
12
tests/qemu-iotests/063.out | 12 ++++++++++++
22
2 files changed, 21 insertions(+), 5 deletions(-)
13
3 files changed, 22 insertions(+)
14
23
15
diff --git a/block/qcow2.c b/block/qcow2.c
24
diff --git a/block/qcow2.c b/block/qcow2.c
16
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
17
--- a/block/qcow2.c
26
--- a/block/qcow2.c
18
+++ b/block/qcow2.c
27
+++ b/block/qcow2.c
19
@@ -XXX,XX +XXX,XX @@ qcow2_co_copy_range_to(BlockDriverState *bs,
28
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
20
}
29
/* Allocate the data area */
21
30
new_file_size = allocation_start +
22
bytes -= cur_bytes;
31
nb_new_data_clusters * s->cluster_size;
23
+ src_offset += cur_bytes;
32
- /* Image file grows, so @exact does not matter */
24
dst_offset += cur_bytes;
33
- ret = bdrv_co_truncate(bs->file, new_file_size, false, prealloc, 0,
25
}
34
- errp);
26
ret = 0;
35
+ /*
27
diff --git a/tests/qemu-iotests/063 b/tests/qemu-iotests/063
36
+ * Image file grows, so @exact does not matter.
28
index XXXXXXX..XXXXXXX 100755
37
+ *
29
--- a/tests/qemu-iotests/063
38
+ * If we need to zero out the new area, try first whether the protocol
30
+++ b/tests/qemu-iotests/063
39
+ * driver can already take care of this.
31
@@ -XXX,XX +XXX,XX @@ if $QEMU_IMG convert -f $IMGFMT -O $IMGFMT -n "$TEST_IMG.orig" "$TEST_IMG" >/dev
40
+ */
32
exit 1
41
+ if (flags & BDRV_REQ_ZERO_WRITE) {
33
fi
42
+ ret = bdrv_co_truncate(bs->file, new_file_size, false, prealloc,
34
43
+ BDRV_REQ_ZERO_WRITE, NULL);
35
+echo "== Regression testing for copy offloading bug =="
44
+ if (ret >= 0) {
36
+
45
+ flags &= ~BDRV_REQ_ZERO_WRITE;
37
+_make_test_img 1M
46
+ }
38
+TEST_IMG="$TEST_IMG.target" _make_test_img 1M
47
+ } else {
39
+$QEMU_IO -c 'write -P 1 0 512k' -c 'write -P 2 512k 512k' "$TEST_IMG" | _filter_qemu_io
48
+ ret = -1;
40
+$QEMU_IO -c 'write -P 4 512k 512k' -c 'write -P 3 0 512k' "$TEST_IMG.target" | _filter_qemu_io
49
+ }
41
+$QEMU_IMG convert -n -O $IMGFMT "$TEST_IMG" "$TEST_IMG.target"
50
+ if (ret < 0) {
42
+$QEMU_IMG compare "$TEST_IMG" "$TEST_IMG.target"
51
+ ret = bdrv_co_truncate(bs->file, new_file_size, false, prealloc, 0,
43
+
52
+ errp);
44
echo "*** done"
53
+ }
45
rm -f $seq.full
54
if (ret < 0) {
46
status=0
55
error_prepend(errp, "Failed to resize underlying file: ");
47
diff --git a/tests/qemu-iotests/063.out b/tests/qemu-iotests/063.out
56
qcow2_free_clusters(bs, allocation_start,
57
diff --git a/tests/qemu-iotests/274.out b/tests/qemu-iotests/274.out
48
index XXXXXXX..XXXXXXX 100644
58
index XXXXXXX..XXXXXXX 100644
49
--- a/tests/qemu-iotests/063.out
59
--- a/tests/qemu-iotests/274.out
50
+++ b/tests/qemu-iotests/063.out
60
+++ b/tests/qemu-iotests/274.out
51
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=4194304
61
@@ -XXX,XX +XXX,XX @@ read 65536/65536 bytes at offset 9437184
52
No errors were found on the image.
62
10 MiB (0xa00000) bytes allocated at offset 5 MiB (0x500000)
53
== Testing conversion to a smaller file fails ==
63
54
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2097152
64
[{ "start": 0, "length": 5242880, "depth": 1, "zero": true, "data": false},
55
+== Regression testing for copy offloading bug ==
65
-{ "start": 5242880, "length": 10485760, "depth": 0, "zero": true, "data": false, "offset": 327680}]
56
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
66
+{ "start": 5242880, "length": 10485760, "depth": 0, "zero": false, "data": true, "offset": 327680}]
57
+Formatting 'TEST_DIR/t.IMGFMT.target', fmt=IMGFMT size=1048576
67
58
+wrote 524288/524288 bytes at offset 0
68
=== preallocation=full ===
59
+512 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
69
Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=16777216 cluster_size=65536 lazy_refcounts=off refcount_bits=16
60
+wrote 524288/524288 bytes at offset 524288
70
@@ -XXX,XX +XXX,XX @@ read 65536/65536 bytes at offset 11534336
61
+512 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
71
4 MiB (0x400000) bytes allocated at offset 8 MiB (0x800000)
62
+wrote 524288/524288 bytes at offset 524288
72
63
+512 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
73
[{ "start": 0, "length": 8388608, "depth": 1, "zero": true, "data": false},
64
+wrote 524288/524288 bytes at offset 0
74
-{ "start": 8388608, "length": 4194304, "depth": 0, "zero": true, "data": false, "offset": 327680}]
65
+512 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
75
+{ "start": 8388608, "length": 4194304, "depth": 0, "zero": false, "data": true, "offset": 327680}]
66
+Images are identical.
76
67
*** done
77
=== preallocation=off ===
78
Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=393216 cluster_size=65536 lazy_refcounts=off refcount_bits=16
68
--
79
--
69
2.13.6
80
2.25.3
70
81
71
82
diff view generated by jsdifflib
1
From: Weiping Zhang <zhangweiping@didichuxing.com>
1
From: Andrzej Jakowski <andrzej.jakowski@linux.intel.com>
2
2
3
Add an optional paramter num_queues for device, and set it
3
This patch introduces support for PMR that has been defined as part of NVMe 1.4
4
to 64 by default.
4
spec. User can now specify a pmrdev option that should point to HostMemoryBackend.
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.
5
8
6
Signed-off-by: Weiping Zhang <zhangweiping@didichuxing.com>
9
Signed-off-by: Andrzej Jakowski <andrzej.jakowski@linux.intel.com>
7
Acked-by: Keith Busch <keith.busch@intel.com>
10
Reviewed-by: Klaus Jensen <k.jensen@samsung.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>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
15
---
10
hw/block/nvme.c | 5 +++--
16
hw/block/nvme.h | 2 +
11
1 file changed, 3 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(-)
12
22
23
diff --git a/hw/block/nvme.h b/hw/block/nvme.h
24
index XXXXXXX..XXXXXXX 100644
25
--- a/hw/block/nvme.h
26
+++ b/hw/block/nvme.h
27
@@ -XXX,XX +XXX,XX @@ typedef struct NvmeCtrl {
28
uint64_t timestamp_set_qemu_clock_ms; /* QEMU clock time */
29
30
char *serial;
31
+ HostMemoryBackend *pmrdev;
32
+
33
NvmeNamespace *namespaces;
34
NvmeSQueue **sq;
35
NvmeCQueue **cq;
36
diff --git a/include/block/nvme.h b/include/block/nvme.h
37
index XXXXXXX..XXXXXXX 100644
38
--- a/include/block/nvme.h
39
+++ b/include/block/nvme.h
40
@@ -XXX,XX +XXX,XX @@ typedef struct NvmeBar {
41
uint64_t acq;
42
uint32_t cmbloc;
43
uint32_t cmbsz;
44
+ uint8_t padding[3520]; /* not used by QEMU */
45
+ uint32_t pmrcap;
46
+ uint32_t pmrctl;
47
+ uint32_t pmrsts;
48
+ uint32_t pmrebs;
49
+ uint32_t pmrswtp;
50
+ uint32_t pmrmsc;
51
} NvmeBar;
52
53
enum NvmeCapShift {
54
@@ -XXX,XX +XXX,XX @@ enum NvmeCapShift {
55
CAP_CSS_SHIFT = 37,
56
CAP_MPSMIN_SHIFT = 48,
57
CAP_MPSMAX_SHIFT = 52,
58
+ CAP_PMR_SHIFT = 56,
59
};
60
61
enum NvmeCapMask {
62
@@ -XXX,XX +XXX,XX @@ enum NvmeCapMask {
63
CAP_CSS_MASK = 0xff,
64
CAP_MPSMIN_MASK = 0xf,
65
CAP_MPSMAX_MASK = 0xf,
66
+ CAP_PMR_MASK = 0x1,
67
};
68
69
#define NVME_CAP_MQES(cap) (((cap) >> CAP_MQES_SHIFT) & CAP_MQES_MASK)
70
@@ -XXX,XX +XXX,XX @@ enum NvmeCapMask {
71
<< CAP_MPSMIN_SHIFT)
72
#define NVME_CAP_SET_MPSMAX(cap, val) (cap |= (uint64_t)(val & CAP_MPSMAX_MASK)\
73
<< CAP_MPSMAX_SHIFT)
74
+#define NVME_CAP_SET_PMRS(cap, val) (cap |= (uint64_t)(val & CAP_PMR_MASK)\
75
+ << CAP_PMR_SHIFT)
76
77
enum NvmeCcShift {
78
CC_EN_SHIFT = 0,
79
@@ -XXX,XX +XXX,XX @@ enum NvmeCmbszMask {
80
#define NVME_CMBSZ_GETSIZE(cmbsz) \
81
(NVME_CMBSZ_SZ(cmbsz) * (1 << (12 + 4 * NVME_CMBSZ_SZU(cmbsz))))
82
83
+enum NvmePmrcapShift {
84
+ PMRCAP_RDS_SHIFT = 3,
85
+ PMRCAP_WDS_SHIFT = 4,
86
+ PMRCAP_BIR_SHIFT = 5,
87
+ PMRCAP_PMRTU_SHIFT = 8,
88
+ PMRCAP_PMRWBM_SHIFT = 10,
89
+ PMRCAP_PMRTO_SHIFT = 16,
90
+ PMRCAP_CMSS_SHIFT = 24,
91
+};
92
+
93
+enum NvmePmrcapMask {
94
+ PMRCAP_RDS_MASK = 0x1,
95
+ PMRCAP_WDS_MASK = 0x1,
96
+ PMRCAP_BIR_MASK = 0x7,
97
+ PMRCAP_PMRTU_MASK = 0x3,
98
+ PMRCAP_PMRWBM_MASK = 0xf,
99
+ PMRCAP_PMRTO_MASK = 0xff,
100
+ PMRCAP_CMSS_MASK = 0x1,
101
+};
102
+
103
+#define NVME_PMRCAP_RDS(pmrcap) \
104
+ ((pmrcap >> PMRCAP_RDS_SHIFT) & PMRCAP_RDS_MASK)
105
+#define NVME_PMRCAP_WDS(pmrcap) \
106
+ ((pmrcap >> PMRCAP_WDS_SHIFT) & PMRCAP_WDS_MASK)
107
+#define NVME_PMRCAP_BIR(pmrcap) \
108
+ ((pmrcap >> PMRCAP_BIR_SHIFT) & PMRCAP_BIR_MASK)
109
+#define NVME_PMRCAP_PMRTU(pmrcap) \
110
+ ((pmrcap >> PMRCAP_PMRTU_SHIFT) & PMRCAP_PMRTU_MASK)
111
+#define NVME_PMRCAP_PMRWBM(pmrcap) \
112
+ ((pmrcap >> PMRCAP_PMRWBM_SHIFT) & PMRCAP_PMRWBM_MASK)
113
+#define NVME_PMRCAP_PMRTO(pmrcap) \
114
+ ((pmrcap >> PMRCAP_PMRTO_SHIFT) & PMRCAP_PMRTO_MASK)
115
+#define NVME_PMRCAP_CMSS(pmrcap) \
116
+ ((pmrcap >> PMRCAP_CMSS_SHIFT) & PMRCAP_CMSS_MASK)
117
+
118
+#define NVME_PMRCAP_SET_RDS(pmrcap, val) \
119
+ (pmrcap |= (uint64_t)(val & PMRCAP_RDS_MASK) << PMRCAP_RDS_SHIFT)
120
+#define NVME_PMRCAP_SET_WDS(pmrcap, val) \
121
+ (pmrcap |= (uint64_t)(val & PMRCAP_WDS_MASK) << PMRCAP_WDS_SHIFT)
122
+#define NVME_PMRCAP_SET_BIR(pmrcap, val) \
123
+ (pmrcap |= (uint64_t)(val & PMRCAP_BIR_MASK) << PMRCAP_BIR_SHIFT)
124
+#define NVME_PMRCAP_SET_PMRTU(pmrcap, val) \
125
+ (pmrcap |= (uint64_t)(val & PMRCAP_PMRTU_MASK) << PMRCAP_PMRTU_SHIFT)
126
+#define NVME_PMRCAP_SET_PMRWBM(pmrcap, val) \
127
+ (pmrcap |= (uint64_t)(val & PMRCAP_PMRWBM_MASK) << PMRCAP_PMRWBM_SHIFT)
128
+#define NVME_PMRCAP_SET_PMRTO(pmrcap, val) \
129
+ (pmrcap |= (uint64_t)(val & PMRCAP_PMRTO_MASK) << PMRCAP_PMRTO_SHIFT)
130
+#define NVME_PMRCAP_SET_CMSS(pmrcap, val) \
131
+ (pmrcap |= (uint64_t)(val & PMRCAP_CMSS_MASK) << PMRCAP_CMSS_SHIFT)
132
+
133
+enum NvmePmrctlShift {
134
+ PMRCTL_EN_SHIFT = 0,
135
+};
136
+
137
+enum NvmePmrctlMask {
138
+ PMRCTL_EN_MASK = 0x1,
139
+};
140
+
141
+#define NVME_PMRCTL_EN(pmrctl) ((pmrctl >> PMRCTL_EN_SHIFT) & PMRCTL_EN_MASK)
142
+
143
+#define NVME_PMRCTL_SET_EN(pmrctl, val) \
144
+ (pmrctl |= (uint64_t)(val & PMRCTL_EN_MASK) << PMRCTL_EN_SHIFT)
145
+
146
+enum NvmePmrstsShift {
147
+ PMRSTS_ERR_SHIFT = 0,
148
+ PMRSTS_NRDY_SHIFT = 8,
149
+ PMRSTS_HSTS_SHIFT = 9,
150
+ PMRSTS_CBAI_SHIFT = 12,
151
+};
152
+
153
+enum NvmePmrstsMask {
154
+ PMRSTS_ERR_MASK = 0xff,
155
+ PMRSTS_NRDY_MASK = 0x1,
156
+ PMRSTS_HSTS_MASK = 0x7,
157
+ PMRSTS_CBAI_MASK = 0x1,
158
+};
159
+
160
+#define NVME_PMRSTS_ERR(pmrsts) \
161
+ ((pmrsts >> PMRSTS_ERR_SHIFT) & PMRSTS_ERR_MASK)
162
+#define NVME_PMRSTS_NRDY(pmrsts) \
163
+ ((pmrsts >> PMRSTS_NRDY_SHIFT) & PMRSTS_NRDY_MASK)
164
+#define NVME_PMRSTS_HSTS(pmrsts) \
165
+ ((pmrsts >> PMRSTS_HSTS_SHIFT) & PMRSTS_HSTS_MASK)
166
+#define NVME_PMRSTS_CBAI(pmrsts) \
167
+ ((pmrsts >> PMRSTS_CBAI_SHIFT) & PMRSTS_CBAI_MASK)
168
+
169
+#define NVME_PMRSTS_SET_ERR(pmrsts, val) \
170
+ (pmrsts |= (uint64_t)(val & PMRSTS_ERR_MASK) << PMRSTS_ERR_SHIFT)
171
+#define NVME_PMRSTS_SET_NRDY(pmrsts, val) \
172
+ (pmrsts |= (uint64_t)(val & PMRSTS_NRDY_MASK) << PMRSTS_NRDY_SHIFT)
173
+#define NVME_PMRSTS_SET_HSTS(pmrsts, val) \
174
+ (pmrsts |= (uint64_t)(val & PMRSTS_HSTS_MASK) << PMRSTS_HSTS_SHIFT)
175
+#define NVME_PMRSTS_SET_CBAI(pmrsts, val) \
176
+ (pmrsts |= (uint64_t)(val & PMRSTS_CBAI_MASK) << PMRSTS_CBAI_SHIFT)
177
+
178
+enum NvmePmrebsShift {
179
+ PMREBS_PMRSZU_SHIFT = 0,
180
+ PMREBS_RBB_SHIFT = 4,
181
+ PMREBS_PMRWBZ_SHIFT = 8,
182
+};
183
+
184
+enum NvmePmrebsMask {
185
+ PMREBS_PMRSZU_MASK = 0xf,
186
+ PMREBS_RBB_MASK = 0x1,
187
+ PMREBS_PMRWBZ_MASK = 0xffffff,
188
+};
189
+
190
+#define NVME_PMREBS_PMRSZU(pmrebs) \
191
+ ((pmrebs >> PMREBS_PMRSZU_SHIFT) & PMREBS_PMRSZU_MASK)
192
+#define NVME_PMREBS_RBB(pmrebs) \
193
+ ((pmrebs >> PMREBS_RBB_SHIFT) & PMREBS_RBB_MASK)
194
+#define NVME_PMREBS_PMRWBZ(pmrebs) \
195
+ ((pmrebs >> PMREBS_PMRWBZ_SHIFT) & PMREBS_PMRWBZ_MASK)
196
+
197
+#define NVME_PMREBS_SET_PMRSZU(pmrebs, val) \
198
+ (pmrebs |= (uint64_t)(val & PMREBS_PMRSZU_MASK) << PMREBS_PMRSZU_SHIFT)
199
+#define NVME_PMREBS_SET_RBB(pmrebs, val) \
200
+ (pmrebs |= (uint64_t)(val & PMREBS_RBB_MASK) << PMREBS_RBB_SHIFT)
201
+#define NVME_PMREBS_SET_PMRWBZ(pmrebs, val) \
202
+ (pmrebs |= (uint64_t)(val & PMREBS_PMRWBZ_MASK) << PMREBS_PMRWBZ_SHIFT)
203
+
204
+enum NvmePmrswtpShift {
205
+ PMRSWTP_PMRSWTU_SHIFT = 0,
206
+ PMRSWTP_PMRSWTV_SHIFT = 8,
207
+};
208
+
209
+enum NvmePmrswtpMask {
210
+ PMRSWTP_PMRSWTU_MASK = 0xf,
211
+ PMRSWTP_PMRSWTV_MASK = 0xffffff,
212
+};
213
+
214
+#define NVME_PMRSWTP_PMRSWTU(pmrswtp) \
215
+ ((pmrswtp >> PMRSWTP_PMRSWTU_SHIFT) & PMRSWTP_PMRSWTU_MASK)
216
+#define NVME_PMRSWTP_PMRSWTV(pmrswtp) \
217
+ ((pmrswtp >> PMRSWTP_PMRSWTV_SHIFT) & PMRSWTP_PMRSWTV_MASK)
218
+
219
+#define NVME_PMRSWTP_SET_PMRSWTU(pmrswtp, val) \
220
+ (pmrswtp |= (uint64_t)(val & PMRSWTP_PMRSWTU_MASK) << PMRSWTP_PMRSWTU_SHIFT)
221
+#define NVME_PMRSWTP_SET_PMRSWTV(pmrswtp, val) \
222
+ (pmrswtp |= (uint64_t)(val & PMRSWTP_PMRSWTV_MASK) << PMRSWTP_PMRSWTV_SHIFT)
223
+
224
+enum NvmePmrmscShift {
225
+ PMRMSC_CMSE_SHIFT = 1,
226
+ PMRMSC_CBA_SHIFT = 12,
227
+};
228
+
229
+enum NvmePmrmscMask {
230
+ PMRMSC_CMSE_MASK = 0x1,
231
+ PMRMSC_CBA_MASK = 0xfffffffffffff,
232
+};
233
+
234
+#define NVME_PMRMSC_CMSE(pmrmsc) \
235
+ ((pmrmsc >> PMRMSC_CMSE_SHIFT) & PMRMSC_CMSE_MASK)
236
+#define NVME_PMRMSC_CBA(pmrmsc) \
237
+ ((pmrmsc >> PMRMSC_CBA_SHIFT) & PMRMSC_CBA_MASK)
238
+
239
+#define NVME_PMRMSC_SET_CMSE(pmrmsc, val) \
240
+ (pmrmsc |= (uint64_t)(val & PMRMSC_CMSE_MASK) << PMRMSC_CMSE_SHIFT)
241
+#define NVME_PMRMSC_SET_CBA(pmrmsc, val) \
242
+ (pmrmsc |= (uint64_t)(val & PMRMSC_CBA_MASK) << PMRMSC_CBA_SHIFT)
243
+
244
typedef struct NvmeCmd {
245
uint8_t opcode;
246
uint8_t fuse;
13
diff --git a/hw/block/nvme.c b/hw/block/nvme.c
247
diff --git a/hw/block/nvme.c b/hw/block/nvme.c
14
index XXXXXXX..XXXXXXX 100644
248
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/block/nvme.c
249
--- a/hw/block/nvme.c
16
+++ b/hw/block/nvme.c
250
+++ b/hw/block/nvme.c
17
@@ -XXX,XX +XXX,XX @@
251
@@ -XXX,XX +XXX,XX @@
18
* Usage: add options:
19
* -drive file=<file>,if=none,id=<drive_id>
252
* -drive file=<file>,if=none,id=<drive_id>
20
* -device nvme,drive=<drive_id>,serial=<serial>,id=<id[optional]>, \
253
* -device nvme,drive=<drive_id>,serial=<serial>,id=<id[optional]>, \
21
- * cmb_size_mb=<cmb_size_mb[optional]>
254
* cmb_size_mb=<cmb_size_mb[optional]>, \
22
+ * cmb_size_mb=<cmb_size_mb[optional]>, \
255
+ * [pmrdev=<mem_backend_file_id>,] \
23
+ * num_queues=<N[optional]>
256
* num_queues=<N[optional]>
24
*
257
*
25
* Note cmb_size_mb denotes size of CMB in MB. CMB is assumed to be at
258
* Note cmb_size_mb denotes size of CMB in MB. CMB is assumed to be at
26
* offset 0 in BAR2 and supports only WDS, RDS and SQS for now.
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,
27
@@ -XXX,XX +XXX,XX @@ static void nvme_realize(PCIDevice *pci_dev, Error **errp)
325
@@ -XXX,XX +XXX,XX @@ static void nvme_realize(PCIDevice *pci_dev, Error **errp)
28
pcie_endpoint_cap_init(&n->parent_obj, 0x80);
326
error_setg(errp, "serial property not set");
29
327
return;
30
n->num_namespaces = 1;
328
}
31
- n->num_queues = 64;
329
+
32
n->reg_size = pow2ceil(0x1004 + 2 * (n->num_queues + 1) * 4);
330
+ if (!n->cmb_size_mb && n->pmrdev) {
33
n->ns_size = bs_size / (uint64_t)n->num_namespaces;
331
+ if (host_memory_backend_is_mapped(n->pmrdev)) {
34
332
+ char *path = object_get_canonical_path_component(OBJECT(n->pmrdev));
35
@@ -XXX,XX +XXX,XX @@ static Property nvme_props[] = {
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[] = {
36
DEFINE_BLOCK_PROPERTIES(NvmeCtrl, conf),
413
DEFINE_BLOCK_PROPERTIES(NvmeCtrl, conf),
414
+ DEFINE_PROP_LINK("pmrdev", NvmeCtrl, pmrdev, TYPE_MEMORY_BACKEND,
415
+ HostMemoryBackend *),
37
DEFINE_PROP_STRING("serial", NvmeCtrl, serial),
416
DEFINE_PROP_STRING("serial", NvmeCtrl, serial),
38
DEFINE_PROP_UINT32("cmb_size_mb", NvmeCtrl, cmb_size_mb, 0),
417
DEFINE_PROP_UINT32("cmb_size_mb", NvmeCtrl, cmb_size_mb, 0),
39
+ DEFINE_PROP_UINT32("num_queues", NvmeCtrl, num_queues, 64),
418
DEFINE_PROP_UINT32("num_queues", NvmeCtrl, num_queues, 64),
40
DEFINE_PROP_END_OF_LIST(),
419
diff --git a/hw/block/Makefile.objs b/hw/block/Makefile.objs
41
};
420
index XXXXXXX..XXXXXXX 100644
42
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""
43
--
452
--
44
2.13.6
453
2.25.3
45
454
46
455
diff view generated by jsdifflib
Deleted patch
1
If qcow2_alloc_clusters_at() returns an error, we do need to negate it
2
to get back the positive errno code for error_setg_errno(), but we still
3
need to return the negative error code.
4
1
5
Fixes: 772d1f973f87269f6a4a4ea4b880680f3779bbdf
6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
8
---
9
block/qcow2.c | 2 +-
10
1 file changed, 1 insertion(+), 1 deletion(-)
11
12
diff --git a/block/qcow2.c b/block/qcow2.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/block/qcow2.c
15
+++ b/block/qcow2.c
16
@@ -XXX,XX +XXX,XX @@ static int qcow2_truncate(BlockDriverState *bs, int64_t offset,
17
if (clusters_allocated < 0) {
18
error_setg_errno(errp, -clusters_allocated,
19
"Failed to allocate data clusters");
20
- return -clusters_allocated;
21
+ return clusters_allocated;
22
}
23
24
assert(clusters_allocated == nb_new_data_clusters);
25
--
26
2.13.6
27
28
diff view generated by jsdifflib
1
All callers are coroutine_fns now, so we can just directly call
1
The QMP handler qmp_object_add() and the implementation of --object in
2
preallocate_co().
2
qemu-storage-daemon can share most of the code. Currently,
3
qemu-storage-daemon calls qmp_object_add(), but this is not correct
4
because different visitors need to be used.
5
6
As a first step towards a fix, make qmp_object_add() a wrapper around a
7
new function user_creatable_add_dict() that can get an additional
8
parameter. The handling of "props" is only required for compatibility
9
and not required for the qemu-storage-daemon command line, so it stays
10
in qmp_object_add().
3
11
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
6
---
13
---
7
block/qcow2.c | 51 ++++++++-------------------------------------------
14
include/qom/object_interfaces.h | 12 ++++++++++++
8
1 file changed, 8 insertions(+), 43 deletions(-)
15
qom/object_interfaces.c | 27 +++++++++++++++++++++++++++
16
qom/qom-qmp-cmds.c | 24 +-----------------------
17
3 files changed, 40 insertions(+), 23 deletions(-)
9
18
10
diff --git a/block/qcow2.c b/block/qcow2.c
19
diff --git a/include/qom/object_interfaces.h b/include/qom/object_interfaces.h
11
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
12
--- a/block/qcow2.c
21
--- a/include/qom/object_interfaces.h
13
+++ b/block/qcow2.c
22
+++ b/include/qom/object_interfaces.h
14
@@ -XXX,XX +XXX,XX @@ static int qcow2_set_up_encryption(BlockDriverState *bs,
23
@@ -XXX,XX +XXX,XX @@ Object *user_creatable_add_type(const char *type, const char *id,
15
return ret;
24
const QDict *qdict,
25
Visitor *v, Error **errp);
26
27
+/**
28
+ * user_creatable_add_dict:
29
+ * @qdict: the object definition
30
+ * @errp: if an error occurs, a pointer to an area to store the error
31
+ *
32
+ * Create an instance of the user creatable object that is defined by
33
+ * @qdict. The object type is taken from the QDict key 'qom-type', its
34
+ * ID from the key 'id'. The remaining entries in @qdict are used to
35
+ * initialize the object properties.
36
+ */
37
+void user_creatable_add_dict(QDict *qdict, Error **errp);
38
+
39
/**
40
* user_creatable_add_opts:
41
* @opts: the object definition
42
diff --git a/qom/object_interfaces.c b/qom/object_interfaces.c
43
index XXXXXXX..XXXXXXX 100644
44
--- a/qom/object_interfaces.c
45
+++ b/qom/object_interfaces.c
46
@@ -XXX,XX +XXX,XX @@
47
#include "qapi/qmp/qerror.h"
48
#include "qapi/qmp/qjson.h"
49
#include "qapi/qmp/qstring.h"
50
+#include "qapi/qobject-input-visitor.h"
51
#include "qom/object_interfaces.h"
52
#include "qemu/help_option.h"
53
#include "qemu/module.h"
54
@@ -XXX,XX +XXX,XX @@ out:
55
return obj;
16
}
56
}
17
57
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;
18
-
107
-
19
-typedef struct PreallocCo {
108
- type = g_strdup(qdict_get_try_str(qdict, "qom-type"));
20
- BlockDriverState *bs;
109
- if (!type) {
21
- uint64_t offset;
110
- error_setg(errp, QERR_MISSING_PARAMETER, "qom-type");
22
- uint64_t new_length;
111
- return;
112
- }
113
- qdict_del(qdict, "qom-type");
23
-
114
-
24
- int ret;
115
- id = g_strdup(qdict_get_try_str(qdict, "id"));
25
-} PreallocCo;
116
- if (!id) {
26
-
117
- error_setg(errp, QERR_MISSING_PARAMETER, "id");
27
/**
118
- return;
28
* Preallocates metadata structures for data clusters between @offset (in the
119
- }
29
* guest disk) and @new_length (which is thus generally the new guest disk
120
- qdict_del(qdict, "id");
30
@@ -XXX,XX +XXX,XX @@ typedef struct PreallocCo {
121
31
*
122
props = qdict_get(qdict, "props");
32
* Returns: 0 on success, -errno on failure.
123
if (props) {
33
*/
124
@@ -XXX,XX +XXX,XX @@ void qmp_object_add(QDict *qdict, QObject **ret_data, Error **errp)
34
-static void coroutine_fn preallocate_co(void *opaque)
125
qobject_unref(pdict);
35
+static int coroutine_fn preallocate_co(BlockDriverState *bs, uint64_t offset,
36
+ uint64_t new_length)
37
{
38
- PreallocCo *params = opaque;
39
- BlockDriverState *bs = params->bs;
40
- uint64_t offset = params->offset;
41
- uint64_t new_length = params->new_length;
42
uint64_t bytes;
43
uint64_t host_offset = 0;
44
unsigned int cur_bytes;
45
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn preallocate_co(void *opaque)
46
ret = qcow2_alloc_cluster_offset(bs, offset, &cur_bytes,
47
&host_offset, &meta);
48
if (ret < 0) {
49
- goto done;
50
+ return ret;
51
}
52
53
while (meta) {
54
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn preallocate_co(void *opaque)
55
if (ret < 0) {
56
qcow2_free_any_clusters(bs, meta->alloc_offset,
57
meta->nb_clusters, QCOW2_DISCARD_NEVER);
58
- goto done;
59
+ return ret;
60
}
61
62
/* There are no dependent requests, but we need to remove our
63
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn preallocate_co(void *opaque)
64
ret = bdrv_pwrite(bs->file, (host_offset + cur_bytes) - 1,
65
&data, 1);
66
if (ret < 0) {
67
- goto done;
68
+ return ret;
69
}
70
}
126
}
71
127
72
- ret = 0;
128
- v = qobject_input_visitor_new(QOBJECT(qdict));
73
-
129
- obj = user_creatable_add_type(type, id, qdict, v, errp);
74
-done:
130
- visit_free(v);
75
- params->ret = ret;
131
- object_unref(obj);
76
-}
132
+ user_creatable_add_dict(qdict, errp);
77
-
78
-static int preallocate(BlockDriverState *bs,
79
- uint64_t offset, uint64_t new_length)
80
-{
81
- PreallocCo params = {
82
- .bs = bs,
83
- .offset = offset,
84
- .new_length = new_length,
85
- .ret = -EINPROGRESS,
86
- };
87
-
88
- if (qemu_in_coroutine()) {
89
- preallocate_co(&params);
90
- } else {
91
- Coroutine *co = qemu_coroutine_create(preallocate_co, &params);
92
- bdrv_coroutine_enter(bs, co);
93
- BDRV_POLL_WHILE(bs, params.ret == -EINPROGRESS);
94
- }
95
- return params.ret;
96
+ return 0;
97
}
133
}
98
134
99
/* qcow2_refcount_metadata_size:
135
void qmp_object_del(const char *id, Error **errp)
100
@@ -XXX,XX +XXX,XX @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp)
101
if (qcow2_opts->preallocation != PREALLOC_MODE_OFF) {
102
BDRVQcow2State *s = blk_bs(blk)->opaque;
103
qemu_co_mutex_lock(&s->lock);
104
- ret = preallocate(blk_bs(blk), 0, qcow2_opts->size);
105
+ ret = preallocate_co(blk_bs(blk), 0, qcow2_opts->size);
106
qemu_co_mutex_unlock(&s->lock);
107
108
if (ret < 0) {
109
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
110
break;
111
112
case PREALLOC_MODE_METADATA:
113
- ret = preallocate(bs, old_length, offset);
114
+ ret = preallocate_co(bs, old_length, offset);
115
if (ret < 0) {
116
error_setg_errno(errp, -ret, "Preallocation failed");
117
goto fail;
118
--
136
--
119
2.13.6
137
2.25.3
120
138
121
139
diff view generated by jsdifflib
Deleted patch
1
This moves the bdrv_truncate() implementation from block.c to block/io.c
2
so it can have access to the tracked requests infrastructure.
3
1
4
This involves making refresh_total_sectors() public (in block_int.h).
5
6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
8
---
9
include/block/block_int.h | 2 +
10
block.c | 111 +---------------------------------------------
11
block/io.c | 109 +++++++++++++++++++++++++++++++++++++++++++++
12
3 files changed, 112 insertions(+), 110 deletions(-)
13
14
diff --git a/include/block/block_int.h b/include/block/block_int.h
15
index XXXXXXX..XXXXXXX 100644
16
--- a/include/block/block_int.h
17
+++ b/include/block/block_int.h
18
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_copy_range_to(BdrvChild *src, uint64_t src_offset,
19
BdrvChild *dst, uint64_t dst_offset,
20
uint64_t bytes, BdrvRequestFlags flags);
21
22
+int refresh_total_sectors(BlockDriverState *bs, int64_t hint);
23
+
24
#endif /* BLOCK_INT_H */
25
diff --git a/block.c b/block.c
26
index XXXXXXX..XXXXXXX 100644
27
--- a/block.c
28
+++ b/block.c
29
@@ -XXX,XX +XXX,XX @@ static int find_image_format(BlockBackend *file, const char *filename,
30
* Set the current 'total_sectors' value
31
* Return 0 on success, -errno on error.
32
*/
33
-static int refresh_total_sectors(BlockDriverState *bs, int64_t hint)
34
+int refresh_total_sectors(BlockDriverState *bs, int64_t hint)
35
{
36
BlockDriver *drv = bs->drv;
37
38
@@ -XXX,XX +XXX,XX @@ static void bdrv_parent_cb_change_media(BlockDriverState *bs, bool load)
39
}
40
}
41
42
-static void bdrv_parent_cb_resize(BlockDriverState *bs)
43
-{
44
- BdrvChild *c;
45
- QLIST_FOREACH(c, &bs->parents, next_parent) {
46
- if (c->role->resize) {
47
- c->role->resize(c);
48
- }
49
- }
50
-}
51
-
52
/*
53
* Sets the backing file link of a BDS. A new reference is created; callers
54
* which don't need their own reference any more must call bdrv_unref().
55
@@ -XXX,XX +XXX,XX @@ exit:
56
}
57
58
/**
59
- * Truncate file to 'offset' bytes (needed only for file protocols)
60
- */
61
-int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset,
62
- PreallocMode prealloc, Error **errp)
63
-{
64
- BlockDriverState *bs = child->bs;
65
- BlockDriver *drv = bs->drv;
66
- int ret;
67
-
68
- assert(child->perm & BLK_PERM_RESIZE);
69
-
70
- /* if bs->drv == NULL, bs is closed, so there's nothing to do here */
71
- if (!drv) {
72
- error_setg(errp, "No medium inserted");
73
- return -ENOMEDIUM;
74
- }
75
- if (offset < 0) {
76
- error_setg(errp, "Image size cannot be negative");
77
- return -EINVAL;
78
- }
79
-
80
- bdrv_inc_in_flight(bs);
81
-
82
- if (!drv->bdrv_co_truncate) {
83
- if (bs->file && drv->is_filter) {
84
- ret = bdrv_co_truncate(bs->file, offset, prealloc, errp);
85
- goto out;
86
- }
87
- error_setg(errp, "Image format driver does not support resize");
88
- ret = -ENOTSUP;
89
- goto out;
90
- }
91
- if (bs->read_only) {
92
- error_setg(errp, "Image is read-only");
93
- ret = -EACCES;
94
- goto out;
95
- }
96
-
97
- assert(!(bs->open_flags & BDRV_O_INACTIVE));
98
-
99
- ret = drv->bdrv_co_truncate(bs, offset, prealloc, errp);
100
- if (ret < 0) {
101
- goto out;
102
- }
103
- ret = refresh_total_sectors(bs, offset >> BDRV_SECTOR_BITS);
104
- if (ret < 0) {
105
- error_setg_errno(errp, -ret, "Could not refresh total sector count");
106
- } else {
107
- offset = bs->total_sectors * BDRV_SECTOR_SIZE;
108
- }
109
- bdrv_dirty_bitmap_truncate(bs, offset);
110
- bdrv_parent_cb_resize(bs);
111
- atomic_inc(&bs->write_gen);
112
-
113
-out:
114
- bdrv_dec_in_flight(bs);
115
- return ret;
116
-}
117
-
118
-typedef struct TruncateCo {
119
- BdrvChild *child;
120
- int64_t offset;
121
- PreallocMode prealloc;
122
- Error **errp;
123
- int ret;
124
-} TruncateCo;
125
-
126
-static void coroutine_fn bdrv_truncate_co_entry(void *opaque)
127
-{
128
- TruncateCo *tco = opaque;
129
- tco->ret = bdrv_co_truncate(tco->child, tco->offset, tco->prealloc,
130
- tco->errp);
131
-}
132
-
133
-int bdrv_truncate(BdrvChild *child, int64_t offset, PreallocMode prealloc,
134
- Error **errp)
135
-{
136
- Coroutine *co;
137
- TruncateCo tco = {
138
- .child = child,
139
- .offset = offset,
140
- .prealloc = prealloc,
141
- .errp = errp,
142
- .ret = NOT_DONE,
143
- };
144
-
145
- if (qemu_in_coroutine()) {
146
- /* Fast-path if already in coroutine context */
147
- bdrv_truncate_co_entry(&tco);
148
- } else {
149
- co = qemu_coroutine_create(bdrv_truncate_co_entry, &tco);
150
- qemu_coroutine_enter(co);
151
- BDRV_POLL_WHILE(child->bs, tco.ret == NOT_DONE);
152
- }
153
-
154
- return tco.ret;
155
-}
156
-
157
-/**
158
* Length of a allocated file in bytes. Sparse files are counted by actual
159
* allocated space. Return < 0 if error or unknown.
160
*/
161
diff --git a/block/io.c b/block/io.c
162
index XXXXXXX..XXXXXXX 100644
163
--- a/block/io.c
164
+++ b/block/io.c
165
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_copy_range(BdrvChild *src, uint64_t src_offset,
166
bdrv_dec_in_flight(dst_bs);
167
return ret;
168
}
169
+
170
+static void bdrv_parent_cb_resize(BlockDriverState *bs)
171
+{
172
+ BdrvChild *c;
173
+ QLIST_FOREACH(c, &bs->parents, next_parent) {
174
+ if (c->role->resize) {
175
+ c->role->resize(c);
176
+ }
177
+ }
178
+}
179
+
180
+/**
181
+ * Truncate file to 'offset' bytes (needed only for file protocols)
182
+ */
183
+int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset,
184
+ PreallocMode prealloc, Error **errp)
185
+{
186
+ BlockDriverState *bs = child->bs;
187
+ BlockDriver *drv = bs->drv;
188
+ int ret;
189
+
190
+ assert(child->perm & BLK_PERM_RESIZE);
191
+
192
+ /* if bs->drv == NULL, bs is closed, so there's nothing to do here */
193
+ if (!drv) {
194
+ error_setg(errp, "No medium inserted");
195
+ return -ENOMEDIUM;
196
+ }
197
+ if (offset < 0) {
198
+ error_setg(errp, "Image size cannot be negative");
199
+ return -EINVAL;
200
+ }
201
+
202
+ bdrv_inc_in_flight(bs);
203
+
204
+ if (!drv->bdrv_co_truncate) {
205
+ if (bs->file && drv->is_filter) {
206
+ ret = bdrv_co_truncate(bs->file, offset, prealloc, errp);
207
+ goto out;
208
+ }
209
+ error_setg(errp, "Image format driver does not support resize");
210
+ ret = -ENOTSUP;
211
+ goto out;
212
+ }
213
+ if (bs->read_only) {
214
+ error_setg(errp, "Image is read-only");
215
+ ret = -EACCES;
216
+ goto out;
217
+ }
218
+
219
+ assert(!(bs->open_flags & BDRV_O_INACTIVE));
220
+
221
+ ret = drv->bdrv_co_truncate(bs, offset, prealloc, errp);
222
+ if (ret < 0) {
223
+ goto out;
224
+ }
225
+ ret = refresh_total_sectors(bs, offset >> BDRV_SECTOR_BITS);
226
+ if (ret < 0) {
227
+ error_setg_errno(errp, -ret, "Could not refresh total sector count");
228
+ } else {
229
+ offset = bs->total_sectors * BDRV_SECTOR_SIZE;
230
+ }
231
+ bdrv_dirty_bitmap_truncate(bs, offset);
232
+ bdrv_parent_cb_resize(bs);
233
+ atomic_inc(&bs->write_gen);
234
+
235
+out:
236
+ bdrv_dec_in_flight(bs);
237
+ return ret;
238
+}
239
+
240
+typedef struct TruncateCo {
241
+ BdrvChild *child;
242
+ int64_t offset;
243
+ PreallocMode prealloc;
244
+ Error **errp;
245
+ int ret;
246
+} TruncateCo;
247
+
248
+static void coroutine_fn bdrv_truncate_co_entry(void *opaque)
249
+{
250
+ TruncateCo *tco = opaque;
251
+ tco->ret = bdrv_co_truncate(tco->child, tco->offset, tco->prealloc,
252
+ tco->errp);
253
+}
254
+
255
+int bdrv_truncate(BdrvChild *child, int64_t offset, PreallocMode prealloc,
256
+ Error **errp)
257
+{
258
+ Coroutine *co;
259
+ TruncateCo tco = {
260
+ .child = child,
261
+ .offset = offset,
262
+ .prealloc = prealloc,
263
+ .errp = errp,
264
+ .ret = NOT_DONE,
265
+ };
266
+
267
+ if (qemu_in_coroutine()) {
268
+ /* Fast-path if already in coroutine context */
269
+ bdrv_truncate_co_entry(&tco);
270
+ } else {
271
+ co = qemu_coroutine_create(bdrv_truncate_co_entry, &tco);
272
+ qemu_coroutine_enter(co);
273
+ BDRV_POLL_WHILE(child->bs, tco.ret == NOT_DONE);
274
+ }
275
+
276
+ return tco.ret;
277
+}
278
--
279
2.13.6
280
281
diff view generated by jsdifflib
Deleted patch
1
This moves the code to resize an image file to the thread pool to avoid
2
blocking.
3
1
4
Creating large images with preallocation with blockdev-create is now
5
actually a background job instead of blocking the monitor (and most
6
other things) until the preallocation has completed.
7
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
10
---
11
include/block/raw-aio.h | 4 +-
12
block/file-posix.c | 266 +++++++++++++++++++++++++++---------------------
13
2 files changed, 154 insertions(+), 116 deletions(-)
14
15
diff --git a/include/block/raw-aio.h b/include/block/raw-aio.h
16
index XXXXXXX..XXXXXXX 100644
17
--- a/include/block/raw-aio.h
18
+++ b/include/block/raw-aio.h
19
@@ -XXX,XX +XXX,XX @@
20
#define QEMU_AIO_DISCARD 0x0010
21
#define QEMU_AIO_WRITE_ZEROES 0x0020
22
#define QEMU_AIO_COPY_RANGE 0x0040
23
+#define QEMU_AIO_TRUNCATE 0x0080
24
#define QEMU_AIO_TYPE_MASK \
25
(QEMU_AIO_READ | \
26
QEMU_AIO_WRITE | \
27
@@ -XXX,XX +XXX,XX @@
28
QEMU_AIO_FLUSH | \
29
QEMU_AIO_DISCARD | \
30
QEMU_AIO_WRITE_ZEROES | \
31
- QEMU_AIO_COPY_RANGE)
32
+ QEMU_AIO_COPY_RANGE | \
33
+ QEMU_AIO_TRUNCATE)
34
35
/* AIO flags */
36
#define QEMU_AIO_MISALIGNED 0x1000
37
diff --git a/block/file-posix.c b/block/file-posix.c
38
index XXXXXXX..XXXXXXX 100644
39
--- a/block/file-posix.c
40
+++ b/block/file-posix.c
41
@@ -XXX,XX +XXX,XX @@ typedef struct RawPosixAIOData {
42
#define aio_ioctl_cmd aio_nbytes /* for QEMU_AIO_IOCTL */
43
off_t aio_offset;
44
int aio_type;
45
- int aio_fd2;
46
- off_t aio_offset2;
47
+ union {
48
+ struct {
49
+ int aio_fd2;
50
+ off_t aio_offset2;
51
+ };
52
+ struct {
53
+ PreallocMode prealloc;
54
+ Error **errp;
55
+ };
56
+ };
57
} RawPosixAIOData;
58
59
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
60
@@ -XXX,XX +XXX,XX @@ static ssize_t handle_aiocb_discard(RawPosixAIOData *aiocb)
61
return ret;
62
}
63
64
+static int handle_aiocb_truncate(RawPosixAIOData *aiocb)
65
+{
66
+ int result = 0;
67
+ int64_t current_length = 0;
68
+ char *buf = NULL;
69
+ struct stat st;
70
+ int fd = aiocb->aio_fildes;
71
+ int64_t offset = aiocb->aio_offset;
72
+ Error **errp = aiocb->errp;
73
+
74
+ if (fstat(fd, &st) < 0) {
75
+ result = -errno;
76
+ error_setg_errno(errp, -result, "Could not stat file");
77
+ return result;
78
+ }
79
+
80
+ current_length = st.st_size;
81
+ if (current_length > offset && aiocb->prealloc != PREALLOC_MODE_OFF) {
82
+ error_setg(errp, "Cannot use preallocation for shrinking files");
83
+ return -ENOTSUP;
84
+ }
85
+
86
+ switch (aiocb->prealloc) {
87
+#ifdef CONFIG_POSIX_FALLOCATE
88
+ case PREALLOC_MODE_FALLOC:
89
+ /*
90
+ * Truncating before posix_fallocate() makes it about twice slower on
91
+ * file systems that do not support fallocate(), trying to check if a
92
+ * block is allocated before allocating it, so don't do that here.
93
+ */
94
+ if (offset != current_length) {
95
+ result = -posix_fallocate(fd, current_length,
96
+ offset - current_length);
97
+ if (result != 0) {
98
+ /* posix_fallocate() doesn't set errno. */
99
+ error_setg_errno(errp, -result,
100
+ "Could not preallocate new data");
101
+ }
102
+ } else {
103
+ result = 0;
104
+ }
105
+ goto out;
106
+#endif
107
+ case PREALLOC_MODE_FULL:
108
+ {
109
+ int64_t num = 0, left = offset - current_length;
110
+ off_t seek_result;
111
+
112
+ /*
113
+ * Knowing the final size from the beginning could allow the file
114
+ * system driver to do less allocations and possibly avoid
115
+ * fragmentation of the file.
116
+ */
117
+ if (ftruncate(fd, offset) != 0) {
118
+ result = -errno;
119
+ error_setg_errno(errp, -result, "Could not resize file");
120
+ goto out;
121
+ }
122
+
123
+ buf = g_malloc0(65536);
124
+
125
+ seek_result = lseek(fd, current_length, SEEK_SET);
126
+ if (seek_result < 0) {
127
+ result = -errno;
128
+ error_setg_errno(errp, -result,
129
+ "Failed to seek to the old end of file");
130
+ goto out;
131
+ }
132
+
133
+ while (left > 0) {
134
+ num = MIN(left, 65536);
135
+ result = write(fd, buf, num);
136
+ if (result < 0) {
137
+ result = -errno;
138
+ error_setg_errno(errp, -result,
139
+ "Could not write zeros for preallocation");
140
+ goto out;
141
+ }
142
+ left -= result;
143
+ }
144
+ if (result >= 0) {
145
+ result = fsync(fd);
146
+ if (result < 0) {
147
+ result = -errno;
148
+ error_setg_errno(errp, -result,
149
+ "Could not flush file to disk");
150
+ goto out;
151
+ }
152
+ }
153
+ goto out;
154
+ }
155
+ case PREALLOC_MODE_OFF:
156
+ if (ftruncate(fd, offset) != 0) {
157
+ result = -errno;
158
+ error_setg_errno(errp, -result, "Could not resize file");
159
+ }
160
+ return result;
161
+ default:
162
+ result = -ENOTSUP;
163
+ error_setg(errp, "Unsupported preallocation mode: %s",
164
+ PreallocMode_str(aiocb->prealloc));
165
+ return result;
166
+ }
167
+
168
+out:
169
+ if (result < 0) {
170
+ if (ftruncate(fd, current_length) < 0) {
171
+ error_report("Failed to restore old file length: %s",
172
+ strerror(errno));
173
+ }
174
+ }
175
+
176
+ g_free(buf);
177
+ return result;
178
+}
179
+
180
static int aio_worker(void *arg)
181
{
182
RawPosixAIOData *aiocb = arg;
183
@@ -XXX,XX +XXX,XX @@ static int aio_worker(void *arg)
184
case QEMU_AIO_COPY_RANGE:
185
ret = handle_aiocb_copy_range(aiocb);
186
break;
187
+ case QEMU_AIO_TRUNCATE:
188
+ ret = handle_aiocb_truncate(aiocb);
189
+ break;
190
default:
191
fprintf(stderr, "invalid aio request (0x%x)\n", aiocb->aio_type);
192
ret = -EINVAL;
193
@@ -XXX,XX +XXX,XX @@ static void raw_close(BlockDriverState *bs)
194
*
195
* Returns: 0 on success, -errno on failure.
196
*/
197
-static int raw_regular_truncate(int fd, int64_t offset, PreallocMode prealloc,
198
- Error **errp)
199
+static int coroutine_fn
200
+raw_regular_truncate(BlockDriverState *bs, int fd, int64_t offset,
201
+ PreallocMode prealloc, Error **errp)
202
{
203
- int result = 0;
204
- int64_t current_length = 0;
205
- char *buf = NULL;
206
- struct stat st;
207
-
208
- if (fstat(fd, &st) < 0) {
209
- result = -errno;
210
- error_setg_errno(errp, -result, "Could not stat file");
211
- return result;
212
- }
213
-
214
- current_length = st.st_size;
215
- if (current_length > offset && prealloc != PREALLOC_MODE_OFF) {
216
- error_setg(errp, "Cannot use preallocation for shrinking files");
217
- return -ENOTSUP;
218
- }
219
-
220
- switch (prealloc) {
221
-#ifdef CONFIG_POSIX_FALLOCATE
222
- case PREALLOC_MODE_FALLOC:
223
- /*
224
- * Truncating before posix_fallocate() makes it about twice slower on
225
- * file systems that do not support fallocate(), trying to check if a
226
- * block is allocated before allocating it, so don't do that here.
227
- */
228
- if (offset != current_length) {
229
- result = -posix_fallocate(fd, current_length, offset - current_length);
230
- if (result != 0) {
231
- /* posix_fallocate() doesn't set errno. */
232
- error_setg_errno(errp, -result,
233
- "Could not preallocate new data");
234
- }
235
- } else {
236
- result = 0;
237
- }
238
- goto out;
239
-#endif
240
- case PREALLOC_MODE_FULL:
241
- {
242
- int64_t num = 0, left = offset - current_length;
243
- off_t seek_result;
244
-
245
- /*
246
- * Knowing the final size from the beginning could allow the file
247
- * system driver to do less allocations and possibly avoid
248
- * fragmentation of the file.
249
- */
250
- if (ftruncate(fd, offset) != 0) {
251
- result = -errno;
252
- error_setg_errno(errp, -result, "Could not resize file");
253
- goto out;
254
- }
255
-
256
- buf = g_malloc0(65536);
257
-
258
- seek_result = lseek(fd, current_length, SEEK_SET);
259
- if (seek_result < 0) {
260
- result = -errno;
261
- error_setg_errno(errp, -result,
262
- "Failed to seek to the old end of file");
263
- goto out;
264
- }
265
-
266
- while (left > 0) {
267
- num = MIN(left, 65536);
268
- result = write(fd, buf, num);
269
- if (result < 0) {
270
- result = -errno;
271
- error_setg_errno(errp, -result,
272
- "Could not write zeros for preallocation");
273
- goto out;
274
- }
275
- left -= result;
276
- }
277
- if (result >= 0) {
278
- result = fsync(fd);
279
- if (result < 0) {
280
- result = -errno;
281
- error_setg_errno(errp, -result,
282
- "Could not flush file to disk");
283
- goto out;
284
- }
285
- }
286
- goto out;
287
- }
288
- case PREALLOC_MODE_OFF:
289
- if (ftruncate(fd, offset) != 0) {
290
- result = -errno;
291
- error_setg_errno(errp, -result, "Could not resize file");
292
- }
293
- return result;
294
- default:
295
- result = -ENOTSUP;
296
- error_setg(errp, "Unsupported preallocation mode: %s",
297
- PreallocMode_str(prealloc));
298
- return result;
299
- }
300
+ RawPosixAIOData *acb = g_new(RawPosixAIOData, 1);
301
+ ThreadPool *pool;
302
303
-out:
304
- if (result < 0) {
305
- if (ftruncate(fd, current_length) < 0) {
306
- error_report("Failed to restore old file length: %s",
307
- strerror(errno));
308
- }
309
- }
310
+ *acb = (RawPosixAIOData) {
311
+ .bs = bs,
312
+ .aio_fildes = fd,
313
+ .aio_type = QEMU_AIO_TRUNCATE,
314
+ .aio_offset = offset,
315
+ .prealloc = prealloc,
316
+ .errp = errp,
317
+ };
318
319
- g_free(buf);
320
- return result;
321
+ /* @bs can be NULL, bdrv_get_aio_context() returns the main context then */
322
+ pool = aio_get_thread_pool(bdrv_get_aio_context(bs));
323
+ return thread_pool_submit_co(pool, aio_worker, acb);
324
}
325
326
static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset,
327
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset,
328
}
329
330
if (S_ISREG(st.st_mode)) {
331
- return raw_regular_truncate(s->fd, offset, prealloc, errp);
332
+ return raw_regular_truncate(bs, s->fd, offset, prealloc, errp);
333
}
334
335
if (prealloc != PREALLOC_MODE_OFF) {
336
@@ -XXX,XX +XXX,XX @@ static int64_t raw_get_allocated_file_size(BlockDriverState *bs)
337
return (int64_t)st.st_blocks * 512;
338
}
339
340
-static int raw_co_create(BlockdevCreateOptions *options, Error **errp)
341
+static int coroutine_fn
342
+raw_co_create(BlockdevCreateOptions *options, Error **errp)
343
{
344
BlockdevCreateOptionsFile *file_opts;
345
int fd;
346
@@ -XXX,XX +XXX,XX @@ static int raw_co_create(BlockdevCreateOptions *options, Error **errp)
347
}
348
349
/* Clear the file by truncating it to 0 */
350
- result = raw_regular_truncate(fd, 0, PREALLOC_MODE_OFF, errp);
351
+ result = raw_regular_truncate(NULL, fd, 0, PREALLOC_MODE_OFF, errp);
352
if (result < 0) {
353
goto out_close;
354
}
355
@@ -XXX,XX +XXX,XX @@ static int raw_co_create(BlockdevCreateOptions *options, Error **errp)
356
357
/* Resize and potentially preallocate the file to the desired
358
* final size */
359
- result = raw_regular_truncate(fd, file_opts->size, file_opts->preallocation,
360
- errp);
361
+ result = raw_regular_truncate(NULL, fd, file_opts->size,
362
+ file_opts->preallocation, errp);
363
if (result < 0) {
364
goto out_close;
365
}
366
--
367
2.13.6
368
369
diff view generated by jsdifflib
Deleted patch
1
From: Fam Zheng <famz@redhat.com>
2
1
3
In the beginning of the function, we initialize the local variable to 0,
4
and in the body of the function, we check the assigned values and exit
5
the loop immediately. So here it can never be non-zero.
6
7
Reported-by: Kevin Wolf <kwolf@redhat.com>
8
Signed-off-by: Fam Zheng <famz@redhat.com>
9
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
10
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
---
13
block/qcow2.c | 2 +-
14
1 file changed, 1 insertion(+), 1 deletion(-)
15
16
diff --git a/block/qcow2.c b/block/qcow2.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/block/qcow2.c
19
+++ b/block/qcow2.c
20
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_handle_l2meta(BlockDriverState *bs,
21
while (l2meta != NULL) {
22
QCowL2Meta *next;
23
24
- if (!ret && link_l2) {
25
+ if (link_l2) {
26
ret = qcow2_alloc_cluster_link_l2(bs, l2meta);
27
if (ret) {
28
goto out;
29
--
30
2.13.6
31
32
diff view generated by jsdifflib
Deleted patch
1
From: Fam Zheng <famz@redhat.com>
2
1
3
in_flight and tracked requests need to be tracked in every layer during
4
recursion. For now the only user is qemu-img convert where overlapping
5
requests and IOThreads don't exist, therefore this change doesn't make
6
much difference form user point of view, but it is incorrect as part of
7
the API. Fix it.
8
9
Reported-by: Kevin Wolf <kwolf@redhat.com>
10
Signed-off-by: Fam Zheng <famz@redhat.com>
11
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
---
14
block/io.c | 59 ++++++++++++++++++++++++++++-------------------------------
15
1 file changed, 28 insertions(+), 31 deletions(-)
16
17
diff --git a/block/io.c b/block/io.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/block/io.c
20
+++ b/block/io.c
21
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_co_copy_range_internal(BdrvChild *src,
22
BdrvRequestFlags flags,
23
bool recurse_src)
24
{
25
+ BdrvTrackedRequest src_req, dst_req;
26
+ BlockDriverState *src_bs = src->bs;
27
+ BlockDriverState *dst_bs = dst->bs;
28
int ret;
29
30
if (!src || !dst || !src->bs || !dst->bs) {
31
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_co_copy_range_internal(BdrvChild *src,
32
|| src->bs->encrypted || dst->bs->encrypted) {
33
return -ENOTSUP;
34
}
35
+ bdrv_inc_in_flight(src_bs);
36
+ bdrv_inc_in_flight(dst_bs);
37
+ tracked_request_begin(&src_req, src_bs, src_offset,
38
+ bytes, BDRV_TRACKED_READ);
39
+ tracked_request_begin(&dst_req, dst_bs, dst_offset,
40
+ bytes, BDRV_TRACKED_WRITE);
41
+
42
+ wait_serialising_requests(&src_req);
43
+ wait_serialising_requests(&dst_req);
44
if (recurse_src) {
45
- return src->bs->drv->bdrv_co_copy_range_from(src->bs,
46
- src, src_offset,
47
- dst, dst_offset,
48
- bytes, flags);
49
+ ret = src->bs->drv->bdrv_co_copy_range_from(src->bs,
50
+ src, src_offset,
51
+ dst, dst_offset,
52
+ bytes, flags);
53
} else {
54
- return dst->bs->drv->bdrv_co_copy_range_to(dst->bs,
55
- src, src_offset,
56
- dst, dst_offset,
57
- bytes, flags);
58
+ ret = dst->bs->drv->bdrv_co_copy_range_to(dst->bs,
59
+ src, src_offset,
60
+ dst, dst_offset,
61
+ bytes, flags);
62
}
63
+ tracked_request_end(&src_req);
64
+ tracked_request_end(&dst_req);
65
+ bdrv_dec_in_flight(src_bs);
66
+ bdrv_dec_in_flight(dst_bs);
67
+ return ret;
68
}
69
70
/* Copy range from @src to @dst.
71
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_copy_range(BdrvChild *src, uint64_t src_offset,
72
BdrvChild *dst, uint64_t dst_offset,
73
uint64_t bytes, BdrvRequestFlags flags)
74
{
75
- BdrvTrackedRequest src_req, dst_req;
76
- BlockDriverState *src_bs = src->bs;
77
- BlockDriverState *dst_bs = dst->bs;
78
- int ret;
79
-
80
- bdrv_inc_in_flight(src_bs);
81
- bdrv_inc_in_flight(dst_bs);
82
- tracked_request_begin(&src_req, src_bs, src_offset,
83
- bytes, BDRV_TRACKED_READ);
84
- tracked_request_begin(&dst_req, dst_bs, dst_offset,
85
- bytes, BDRV_TRACKED_WRITE);
86
-
87
- wait_serialising_requests(&src_req);
88
- wait_serialising_requests(&dst_req);
89
- ret = bdrv_co_copy_range_from(src, src_offset,
90
- dst, dst_offset,
91
- bytes, flags);
92
-
93
- tracked_request_end(&src_req);
94
- tracked_request_end(&dst_req);
95
- bdrv_dec_in_flight(src_bs);
96
- bdrv_dec_in_flight(dst_bs);
97
- return ret;
98
+ return bdrv_co_copy_range_from(src, src_offset,
99
+ dst, dst_offset,
100
+ bytes, flags);
101
}
102
103
static void bdrv_parent_cb_resize(BlockDriverState *bs)
104
--
105
2.13.6
106
107
diff view generated by jsdifflib
Deleted patch
1
Commit abf754fe406 updated 026.out, but forgot to also update
2
026.out.nocache.
3
1
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
Reviewed-by: Max Reitz <mreitz@redhat.com>
6
---
7
tests/qemu-iotests/026.out.nocache | 6 +++---
8
1 file changed, 3 insertions(+), 3 deletions(-)
9
10
diff --git a/tests/qemu-iotests/026.out.nocache b/tests/qemu-iotests/026.out.nocache
11
index XXXXXXX..XXXXXXX 100644
12
--- a/tests/qemu-iotests/026.out.nocache
13
+++ b/tests/qemu-iotests/026.out.nocache
14
@@ -XXX,XX +XXX,XX @@ Failed to flush the L2 table cache: No space left on device
15
Failed to flush the refcount block cache: No space left on device
16
write failed: No space left on device
17
18
-11 leaked clusters were found on the image.
19
+10 leaked clusters were found on the image.
20
This means waste of disk space, but no harm to data.
21
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
22
23
@@ -XXX,XX +XXX,XX @@ Failed to flush the L2 table cache: No space left on device
24
Failed to flush the refcount block cache: No space left on device
25
write failed: No space left on device
26
27
-11 leaked clusters were found on the image.
28
+10 leaked clusters were found on the image.
29
This means waste of disk space, but no harm to data.
30
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
31
32
@@ -XXX,XX +XXX,XX @@ Failed to flush the L2 table cache: No space left on device
33
Failed to flush the refcount block cache: No space left on device
34
write failed: No space left on device
35
36
-11 leaked clusters were found on the image.
37
+10 leaked clusters were found on the image.
38
This means waste of disk space, but no harm to data.
39
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
40
41
--
42
2.13.6
43
44
diff view generated by jsdifflib
Deleted patch
1
This simplifies file-posix by implementing the coroutine variants of
2
the discard and flush BlockDriver callbacks. These were the last
3
remaining users of paio_submit(), which can be removed now.
4
1
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
Reviewed-by: Eric Blake <eblake@redhat.com>
7
---
8
block/file-posix.c | 72 ++++++++++++++++++------------------------------------
9
1 file changed, 24 insertions(+), 48 deletions(-)
10
11
diff --git a/block/file-posix.c b/block/file-posix.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/block/file-posix.c
14
+++ b/block/file-posix.c
15
@@ -XXX,XX +XXX,XX @@ static inline int paio_submit_co(BlockDriverState *bs, int fd,
16
return paio_submit_co_full(bs, fd, offset, -1, 0, qiov, bytes, type);
17
}
18
19
-static BlockAIOCB *paio_submit(BlockDriverState *bs, int fd,
20
- int64_t offset, QEMUIOVector *qiov, int bytes,
21
- BlockCompletionFunc *cb, void *opaque, int type)
22
-{
23
- RawPosixAIOData *acb = g_new(RawPosixAIOData, 1);
24
- ThreadPool *pool;
25
-
26
- acb->bs = bs;
27
- acb->aio_type = type;
28
- acb->aio_fildes = fd;
29
-
30
- acb->aio_nbytes = bytes;
31
- acb->aio_offset = offset;
32
-
33
- if (qiov) {
34
- acb->aio_iov = qiov->iov;
35
- acb->aio_niov = qiov->niov;
36
- assert(qiov->size == acb->aio_nbytes);
37
- }
38
-
39
- trace_paio_submit(acb, opaque, offset, bytes, type);
40
- pool = aio_get_thread_pool(bdrv_get_aio_context(bs));
41
- return thread_pool_submit_aio(pool, aio_worker, acb, cb, opaque);
42
-}
43
-
44
static int coroutine_fn raw_co_prw(BlockDriverState *bs, uint64_t offset,
45
uint64_t bytes, QEMUIOVector *qiov, int type)
46
{
47
@@ -XXX,XX +XXX,XX @@ static void raw_aio_unplug(BlockDriverState *bs)
48
#endif
49
}
50
51
-static BlockAIOCB *raw_aio_flush(BlockDriverState *bs,
52
- BlockCompletionFunc *cb, void *opaque)
53
+static int raw_co_flush_to_disk(BlockDriverState *bs)
54
{
55
BDRVRawState *s = bs->opaque;
56
+ int ret;
57
58
- if (fd_open(bs) < 0)
59
- return NULL;
60
+ ret = fd_open(bs);
61
+ if (ret < 0) {
62
+ return ret;
63
+ }
64
65
- return paio_submit(bs, s->fd, 0, NULL, 0, cb, opaque, QEMU_AIO_FLUSH);
66
+ return paio_submit_co(bs, s->fd, 0, NULL, 0, QEMU_AIO_FLUSH);
67
}
68
69
static void raw_aio_attach_aio_context(BlockDriverState *bs,
70
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn raw_co_invalidate_cache(BlockDriverState *bs,
71
#endif /* !__linux__ */
72
}
73
74
-static coroutine_fn BlockAIOCB *raw_aio_pdiscard(BlockDriverState *bs,
75
- int64_t offset, int bytes,
76
- BlockCompletionFunc *cb, void *opaque)
77
+static coroutine_fn int
78
+raw_co_pdiscard(BlockDriverState *bs, int64_t offset, int bytes)
79
{
80
BDRVRawState *s = bs->opaque;
81
82
- return paio_submit(bs, s->fd, offset, NULL, bytes,
83
- cb, opaque, QEMU_AIO_DISCARD);
84
+ return paio_submit_co(bs, s->fd, offset, NULL, bytes, QEMU_AIO_DISCARD);
85
}
86
87
static int coroutine_fn raw_co_pwrite_zeroes(
88
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_file = {
89
90
.bdrv_co_preadv = raw_co_preadv,
91
.bdrv_co_pwritev = raw_co_pwritev,
92
- .bdrv_aio_flush = raw_aio_flush,
93
- .bdrv_aio_pdiscard = raw_aio_pdiscard,
94
+ .bdrv_co_flush_to_disk = raw_co_flush_to_disk,
95
+ .bdrv_co_pdiscard = raw_co_pdiscard,
96
.bdrv_co_copy_range_from = raw_co_copy_range_from,
97
.bdrv_co_copy_range_to = raw_co_copy_range_to,
98
.bdrv_refresh_limits = raw_refresh_limits,
99
@@ -XXX,XX +XXX,XX @@ static int fd_open(BlockDriverState *bs)
100
return -EIO;
101
}
102
103
-static coroutine_fn BlockAIOCB *hdev_aio_pdiscard(BlockDriverState *bs,
104
- int64_t offset, int bytes,
105
- BlockCompletionFunc *cb, void *opaque)
106
+static coroutine_fn int
107
+hdev_co_pdiscard(BlockDriverState *bs, int64_t offset, int bytes)
108
{
109
BDRVRawState *s = bs->opaque;
110
+ int ret;
111
112
- if (fd_open(bs) < 0) {
113
- return NULL;
114
+ ret = fd_open(bs);
115
+ if (ret < 0) {
116
+ return ret;
117
}
118
- return paio_submit(bs, s->fd, offset, NULL, bytes,
119
- cb, opaque, QEMU_AIO_DISCARD|QEMU_AIO_BLKDEV);
120
+ return paio_submit_co(bs, s->fd, offset, NULL, bytes,
121
+ QEMU_AIO_DISCARD | QEMU_AIO_BLKDEV);
122
}
123
124
static coroutine_fn int hdev_co_pwrite_zeroes(BlockDriverState *bs,
125
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_host_device = {
126
127
.bdrv_co_preadv = raw_co_preadv,
128
.bdrv_co_pwritev = raw_co_pwritev,
129
- .bdrv_aio_flush    = raw_aio_flush,
130
- .bdrv_aio_pdiscard = hdev_aio_pdiscard,
131
+ .bdrv_co_flush_to_disk = raw_co_flush_to_disk,
132
+ .bdrv_co_pdiscard = hdev_co_pdiscard,
133
.bdrv_co_copy_range_from = raw_co_copy_range_from,
134
.bdrv_co_copy_range_to = raw_co_copy_range_to,
135
.bdrv_refresh_limits = raw_refresh_limits,
136
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_host_cdrom = {
137
138
.bdrv_co_preadv = raw_co_preadv,
139
.bdrv_co_pwritev = raw_co_pwritev,
140
- .bdrv_aio_flush    = raw_aio_flush,
141
+ .bdrv_co_flush_to_disk = raw_co_flush_to_disk,
142
.bdrv_refresh_limits = raw_refresh_limits,
143
.bdrv_io_plug = raw_aio_plug,
144
.bdrv_io_unplug = raw_aio_unplug,
145
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_host_cdrom = {
146
147
.bdrv_co_preadv = raw_co_preadv,
148
.bdrv_co_pwritev = raw_co_pwritev,
149
- .bdrv_aio_flush    = raw_aio_flush,
150
+ .bdrv_co_flush_to_disk = raw_co_flush_to_disk,
151
.bdrv_refresh_limits = raw_refresh_limits,
152
.bdrv_io_plug = raw_aio_plug,
153
.bdrv_io_unplug = raw_aio_unplug,
154
--
155
2.13.6
156
157
diff view generated by jsdifflib
Deleted patch
1
From: Fam Zheng <famz@redhat.com>
2
1
3
Per SCSI definition the designator_length we receive from INQUIRY is 8,
4
12 or at most 16, but we should be careful because the remote iscsi
5
target may misbehave, otherwise we could have a buffer overflow.
6
7
Reported-by: Max Reitz <mreitz@redhat.com>
8
Signed-off-by: Fam Zheng <famz@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
11
block/iscsi.c | 2 +-
12
1 file changed, 1 insertion(+), 1 deletion(-)
13
14
diff --git a/block/iscsi.c b/block/iscsi.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/block/iscsi.c
17
+++ b/block/iscsi.c
18
@@ -XXX,XX +XXX,XX @@ static void iscsi_populate_target_desc(unsigned char *desc, IscsiLun *lun)
19
desc[5] = (dd->designator_type & 0xF)
20
| ((dd->association & 3) << 4);
21
desc[7] = dd->designator_length;
22
- memcpy(desc + 8, dd->designator, dd->designator_length);
23
+ memcpy(desc + 8, dd->designator, MIN(dd->designator_length, 20));
24
25
desc[28] = 0;
26
desc[29] = (lun->block_size >> 16) & 0xFF;
27
--
28
2.13.6
29
30
diff view generated by jsdifflib
Deleted patch
1
From: Eric Blake <eblake@redhat.com>
2
1
3
We are gradually moving away from sector-based interfaces, towards
4
byte-based. Make the change for the last few sector-based calls
5
into the block layer from the parallels driver.
6
7
Ideally, the parallels driver should switch to doing everything
8
byte-based, but that's a more invasive change that requires a
9
bit more auditing.
10
11
Signed-off-by: Eric Blake <eblake@redhat.com>
12
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
13
Reviewed-by: Denis V. Lunev <den@openvz.org>
14
Reviewed-by: Jeff Cody <jcody@redhat.com>
15
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
16
---
17
block/parallels.c | 16 ++++++++++------
18
1 file changed, 10 insertions(+), 6 deletions(-)
19
20
diff --git a/block/parallels.c b/block/parallels.c
21
index XXXXXXX..XXXXXXX 100644
22
--- a/block/parallels.c
23
+++ b/block/parallels.c
24
@@ -XXX,XX +XXX,XX @@ static int64_t allocate_clusters(BlockDriverState *bs, int64_t sector_num,
25
};
26
qemu_iovec_init_external(&qiov, &iov, 1);
27
28
- ret = bdrv_co_readv(bs->backing, idx * s->tracks, nb_cow_sectors,
29
- &qiov);
30
+ ret = bdrv_co_preadv(bs->backing, idx * s->tracks * BDRV_SECTOR_SIZE,
31
+ nb_cow_bytes, &qiov, 0);
32
if (ret < 0) {
33
qemu_vfree(iov.iov_base);
34
return ret;
35
}
36
37
- ret = bdrv_co_writev(bs->file, s->data_end, nb_cow_sectors, &qiov);
38
+ ret = bdrv_co_pwritev(bs->file, s->data_end * BDRV_SECTOR_SIZE,
39
+ nb_cow_bytes, &qiov, 0);
40
qemu_vfree(iov.iov_base);
41
if (ret < 0) {
42
return ret;
43
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int parallels_co_writev(BlockDriverState *bs,
44
qemu_iovec_reset(&hd_qiov);
45
qemu_iovec_concat(&hd_qiov, qiov, bytes_done, nbytes);
46
47
- ret = bdrv_co_writev(bs->file, position, n, &hd_qiov);
48
+ ret = bdrv_co_pwritev(bs->file, position * BDRV_SECTOR_SIZE, nbytes,
49
+ &hd_qiov, 0);
50
if (ret < 0) {
51
break;
52
}
53
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int parallels_co_readv(BlockDriverState *bs,
54
55
if (position < 0) {
56
if (bs->backing) {
57
- ret = bdrv_co_readv(bs->backing, sector_num, n, &hd_qiov);
58
+ ret = bdrv_co_preadv(bs->backing, sector_num * BDRV_SECTOR_SIZE,
59
+ nbytes, &hd_qiov, 0);
60
if (ret < 0) {
61
break;
62
}
63
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int parallels_co_readv(BlockDriverState *bs,
64
qemu_iovec_memset(&hd_qiov, 0, 0, nbytes);
65
}
66
} else {
67
- ret = bdrv_co_readv(bs->file, position, n, &hd_qiov);
68
+ ret = bdrv_co_preadv(bs->file, position * BDRV_SECTOR_SIZE, nbytes,
69
+ &hd_qiov, 0);
70
if (ret < 0) {
71
break;
72
}
73
--
74
2.13.6
75
76
diff view generated by jsdifflib
Deleted patch
1
From: Eric Blake <eblake@redhat.com>
2
1
3
We are gradually moving away from sector-based interfaces, towards
4
byte-based. Make the change for the internal helper function
5
get_cluster_offset(), by changing n_start and n_end to be byte
6
offsets rather than sector indices within the cluster being
7
allocated. However, assert that these values are still
8
sector-aligned (at least qcrypto_block_encrypt() still wants that).
9
For now we get that alignment for free because we still use
10
sector-based driver callbacks.
11
12
A later patch will then switch the qcow driver as a whole over
13
to byte-based operation; but will still leave things at sector
14
alignments as it is not worth auditing the qcow image format
15
to worry about sub-sector requests.
16
17
Signed-off-by: Eric Blake <eblake@redhat.com>
18
Reviewed-by: Jeff Cody <jcody@redhat.com>
19
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
20
---
21
block/qcow.c | 29 +++++++++++++++--------------
22
1 file changed, 15 insertions(+), 14 deletions(-)
23
24
diff --git a/block/qcow.c b/block/qcow.c
25
index XXXXXXX..XXXXXXX 100644
26
--- a/block/qcow.c
27
+++ b/block/qcow.c
28
@@ -XXX,XX +XXX,XX @@ static int qcow_reopen_prepare(BDRVReopenState *state,
29
*
30
* 0 to not allocate.
31
*
32
- * 1 to allocate a normal cluster (for sector indexes 'n_start' to
33
- * 'n_end')
34
+ * 1 to allocate a normal cluster (for sector-aligned byte offsets 'n_start'
35
+ * to 'n_end' within the cluster)
36
*
37
* 2 to allocate a compressed cluster of size
38
* 'compressed_size'. 'compressed_size' must be > 0 and <
39
@@ -XXX,XX +XXX,XX @@ static int get_cluster_offset(BlockDriverState *bs,
40
if (!allocate)
41
return 0;
42
BLKDBG_EVENT(bs->file, BLKDBG_CLUSTER_ALLOC);
43
+ assert(QEMU_IS_ALIGNED(n_start | n_end, BDRV_SECTOR_SIZE));
44
/* allocate a new cluster */
45
if ((cluster_offset & QCOW_OFLAG_COMPRESSED) &&
46
- (n_end - n_start) < s->cluster_sectors) {
47
+ (n_end - n_start) < s->cluster_size) {
48
/* if the cluster is already compressed, we must
49
decompress it in the case it is not completely
50
overwritten */
51
@@ -XXX,XX +XXX,XX @@ static int get_cluster_offset(BlockDriverState *bs,
52
/* if encrypted, we must initialize the cluster
53
content which won't be written */
54
if (bs->encrypted &&
55
- (n_end - n_start) < s->cluster_sectors) {
56
- uint64_t start_sect;
57
+ (n_end - n_start) < s->cluster_size) {
58
+ uint64_t start_offset;
59
assert(s->crypto);
60
- start_sect = (offset & ~(s->cluster_size - 1)) >> 9;
61
- for(i = 0; i < s->cluster_sectors; i++) {
62
+ start_offset = offset & ~(s->cluster_size - 1);
63
+ for (i = 0; i < s->cluster_size; i += BDRV_SECTOR_SIZE) {
64
if (i < n_start || i >= n_end) {
65
- memset(s->cluster_data, 0x00, 512);
66
+ memset(s->cluster_data, 0x00, BDRV_SECTOR_SIZE);
67
if (qcrypto_block_encrypt(s->crypto,
68
- (start_sect + i) *
69
- BDRV_SECTOR_SIZE,
70
+ start_offset + i,
71
s->cluster_data,
72
BDRV_SECTOR_SIZE,
73
NULL) < 0) {
74
@@ -XXX,XX +XXX,XX @@ static int get_cluster_offset(BlockDriverState *bs,
75
}
76
BLKDBG_EVENT(bs->file, BLKDBG_WRITE_AIO);
77
ret = bdrv_pwrite(bs->file,
78
- cluster_offset + i * 512,
79
- s->cluster_data, 512);
80
+ cluster_offset + i,
81
+ s->cluster_data,
82
+ BDRV_SECTOR_SIZE);
83
if (ret < 0) {
84
return ret;
85
}
86
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow_co_writev(BlockDriverState *bs, int64_t sector_num,
87
n = nb_sectors;
88
}
89
ret = get_cluster_offset(bs, sector_num << 9, 1, 0,
90
- index_in_cluster,
91
- index_in_cluster + n, &cluster_offset);
92
+ index_in_cluster << 9,
93
+ (index_in_cluster + n) << 9, &cluster_offset);
94
if (ret < 0) {
95
break;
96
}
97
--
98
2.13.6
99
100
diff view generated by jsdifflib
Deleted patch
1
From: Eric Blake <eblake@redhat.com>
2
1
3
We are gradually moving away from sector-based interfaces, towards
4
byte-based. Make the change for the internals of the qcow
5
driver read function, by iterating over offset/bytes instead of
6
sector_num/nb_sectors, and with a rename of index_in_cluster and
7
repurposing of n to track bytes instead of sectors.
8
9
A later patch will then switch the qcow driver as a whole over
10
to byte-based operation.
11
12
Signed-off-by: Eric Blake <eblake@redhat.com>
13
Reviewed-by: Jeff Cody <jcody@redhat.com>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
---
16
block/qcow.c | 42 ++++++++++++++++++++----------------------
17
1 file changed, 20 insertions(+), 22 deletions(-)
18
19
diff --git a/block/qcow.c b/block/qcow.c
20
index XXXXXXX..XXXXXXX 100644
21
--- a/block/qcow.c
22
+++ b/block/qcow.c
23
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow_co_readv(BlockDriverState *bs, int64_t sector_num,
24
int nb_sectors, QEMUIOVector *qiov)
25
{
26
BDRVQcowState *s = bs->opaque;
27
- int index_in_cluster;
28
+ int offset_in_cluster;
29
int ret = 0, n;
30
uint64_t cluster_offset;
31
struct iovec hd_iov;
32
QEMUIOVector hd_qiov;
33
uint8_t *buf;
34
void *orig_buf;
35
+ int64_t offset = sector_num * BDRV_SECTOR_SIZE;
36
+ int64_t bytes = nb_sectors * BDRV_SECTOR_SIZE;
37
38
if (qiov->niov > 1) {
39
buf = orig_buf = qemu_try_blockalign(bs, qiov->size);
40
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow_co_readv(BlockDriverState *bs, int64_t sector_num,
41
42
qemu_co_mutex_lock(&s->lock);
43
44
- while (nb_sectors != 0) {
45
+ while (bytes != 0) {
46
/* prepare next request */
47
- ret = get_cluster_offset(bs, sector_num << 9,
48
- 0, 0, 0, 0, &cluster_offset);
49
+ ret = get_cluster_offset(bs, offset, 0, 0, 0, 0, &cluster_offset);
50
if (ret < 0) {
51
break;
52
}
53
- index_in_cluster = sector_num & (s->cluster_sectors - 1);
54
- n = s->cluster_sectors - index_in_cluster;
55
- if (n > nb_sectors) {
56
- n = nb_sectors;
57
+ offset_in_cluster = offset & (s->cluster_size - 1);
58
+ n = s->cluster_size - offset_in_cluster;
59
+ if (n > bytes) {
60
+ n = bytes;
61
}
62
63
if (!cluster_offset) {
64
if (bs->backing) {
65
/* read from the base image */
66
hd_iov.iov_base = (void *)buf;
67
- hd_iov.iov_len = n * 512;
68
+ hd_iov.iov_len = n;
69
qemu_iovec_init_external(&hd_qiov, &hd_iov, 1);
70
qemu_co_mutex_unlock(&s->lock);
71
/* qcow2 emits this on bs->file instead of bs->backing */
72
BLKDBG_EVENT(bs->file, BLKDBG_READ_BACKING_AIO);
73
- ret = bdrv_co_readv(bs->backing, sector_num, n, &hd_qiov);
74
+ ret = bdrv_co_preadv(bs->backing, offset, n, &hd_qiov, 0);
75
qemu_co_mutex_lock(&s->lock);
76
if (ret < 0) {
77
break;
78
}
79
} else {
80
/* Note: in this case, no need to wait */
81
- memset(buf, 0, 512 * n);
82
+ memset(buf, 0, n);
83
}
84
} else if (cluster_offset & QCOW_OFLAG_COMPRESSED) {
85
/* add AIO support for compressed blocks ? */
86
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow_co_readv(BlockDriverState *bs, int64_t sector_num,
87
ret = -EIO;
88
break;
89
}
90
- memcpy(buf,
91
- s->cluster_cache + index_in_cluster * 512, 512 * n);
92
+ memcpy(buf, s->cluster_cache + offset_in_cluster, n);
93
} else {
94
if ((cluster_offset & 511) != 0) {
95
ret = -EIO;
96
break;
97
}
98
hd_iov.iov_base = (void *)buf;
99
- hd_iov.iov_len = n * 512;
100
+ hd_iov.iov_len = n;
101
qemu_iovec_init_external(&hd_qiov, &hd_iov, 1);
102
qemu_co_mutex_unlock(&s->lock);
103
BLKDBG_EVENT(bs->file, BLKDBG_READ_AIO);
104
- ret = bdrv_co_readv(bs->file,
105
- (cluster_offset >> 9) + index_in_cluster,
106
- n, &hd_qiov);
107
+ ret = bdrv_co_preadv(bs->file, cluster_offset + offset_in_cluster,
108
+ n, &hd_qiov, 0);
109
qemu_co_mutex_lock(&s->lock);
110
if (ret < 0) {
111
break;
112
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow_co_readv(BlockDriverState *bs, int64_t sector_num,
113
if (bs->encrypted) {
114
assert(s->crypto);
115
if (qcrypto_block_decrypt(s->crypto,
116
- sector_num * BDRV_SECTOR_SIZE, buf,
117
- n * BDRV_SECTOR_SIZE, NULL) < 0) {
118
+ offset, buf, n, NULL) < 0) {
119
ret = -EIO;
120
break;
121
}
122
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow_co_readv(BlockDriverState *bs, int64_t sector_num,
123
}
124
ret = 0;
125
126
- nb_sectors -= n;
127
- sector_num += n;
128
- buf += n * 512;
129
+ bytes -= n;
130
+ offset += n;
131
+ buf += n;
132
}
133
134
qemu_co_mutex_unlock(&s->lock);
135
--
136
2.13.6
137
138
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
1
After processing the option string with the keyval parser, we get a
2
QDict that contains only strings. This QDict must be fed to a keyval
3
visitor which converts the strings into the right data types.
2
4
3
We are gradually moving away from sector-based interfaces, towards
5
qmp_object_add(), however, uses the normal QObject input visitor, which
4
byte-based. Make the change for the internals of the qcow
6
expects a QDict where all properties already have the QType that matches
5
driver write function, by iterating over offset/bytes instead of
7
the data type required by the QOM object type.
6
sector_num/nb_sectors, and with a rename of index_in_cluster and
7
repurposing of n to track bytes instead of sectors.
8
8
9
A later patch will then switch the qcow driver as a whole over
9
Change the --object implementation in qemu-storage-daemon so that it
10
to byte-based operation.
10
doesn't call qmp_object_add(), but calls user_creatable_add_dict()
11
directly instead and pass it a new keyval boolean that decides which
12
visitor must be used.
11
13
12
Signed-off-by: Eric Blake <eblake@redhat.com>
14
Reported-by: Coiby Xu <coiby.xu@gmail.com>
13
Reviewed-by: Jeff Cody <jcody@redhat.com>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
---
16
---
16
block/qcow.c | 36 +++++++++++++++++-------------------
17
include/qom/object_interfaces.h | 6 +++++-
17
1 file changed, 17 insertions(+), 19 deletions(-)
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(-)
18
22
19
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
20
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
21
--- a/block/qcow.c
25
--- a/include/qom/object_interfaces.h
22
+++ b/block/qcow.c
26
+++ b/include/qom/object_interfaces.h
23
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow_co_writev(BlockDriverState *bs, int64_t sector_num,
27
@@ -XXX,XX +XXX,XX @@ Object *user_creatable_add_type(const char *type, const char *id,
24
int flags)
28
/**
25
{
29
* user_creatable_add_dict:
26
BDRVQcowState *s = bs->opaque;
30
* @qdict: the object definition
27
- int index_in_cluster;
31
+ * @keyval: if true, use a keyval visitor for processing @qdict (i.e.
28
+ int offset_in_cluster;
32
+ * assume that all @qdict values are strings); otherwise, use
29
uint64_t cluster_offset;
33
+ * the normal QObject visitor (i.e. assume all @qdict values
30
int ret = 0, n;
34
+ * have the QType expected by the QOM object type)
31
struct iovec hd_iov;
35
* @errp: if an error occurs, a pointer to an area to store the error
32
QEMUIOVector hd_qiov;
36
*
33
uint8_t *buf;
37
* Create an instance of the user creatable object that is defined by
34
void *orig_buf;
38
@@ -XXX,XX +XXX,XX @@ Object *user_creatable_add_type(const char *type, const char *id,
35
+ int64_t offset = sector_num * BDRV_SECTOR_SIZE;
39
* ID from the key 'id'. The remaining entries in @qdict are used to
36
+ int64_t bytes = nb_sectors * BDRV_SECTOR_SIZE;
40
* initialize the object properties.
37
41
*/
38
assert(!flags);
42
-void user_creatable_add_dict(QDict *qdict, Error **errp);
39
s->cluster_cache_offset = -1; /* disable compressed cache */
43
+void user_creatable_add_dict(QDict *qdict, bool keyval, Error **errp);
40
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow_co_writev(BlockDriverState *bs, int64_t sector_num,
44
41
45
/**
42
qemu_co_mutex_lock(&s->lock);
46
* user_creatable_add_opts:
43
47
diff --git a/qemu-storage-daemon.c b/qemu-storage-daemon.c
44
- while (nb_sectors != 0) {
48
index XXXXXXX..XXXXXXX 100644
45
-
49
--- a/qemu-storage-daemon.c
46
- index_in_cluster = sector_num & (s->cluster_sectors - 1);
50
+++ b/qemu-storage-daemon.c
47
- n = s->cluster_sectors - index_in_cluster;
51
@@ -XXX,XX +XXX,XX @@ static void process_options(int argc, char *argv[])
48
- if (n > nb_sectors) {
52
QemuOpts *opts;
49
- n = nb_sectors;
53
const char *type;
50
+ while (bytes != 0) {
54
QDict *args;
51
+ offset_in_cluster = offset & (s->cluster_size - 1);
55
- QObject *ret_data = NULL;
52
+ n = s->cluster_size - offset_in_cluster;
56
53
+ if (n > bytes) {
57
/* FIXME The keyval parser rejects 'help' arguments, so we must
54
+ n = bytes;
58
* unconditionall try QemuOpts first. */
55
}
59
@@ -XXX,XX +XXX,XX @@ static void process_options(int argc, char *argv[])
56
- ret = get_cluster_offset(bs, sector_num << 9, 1, 0,
60
qemu_opts_del(opts);
57
- index_in_cluster << 9,
61
58
- (index_in_cluster + n) << 9, &cluster_offset);
62
args = keyval_parse(optarg, "qom-type", &error_fatal);
59
+ ret = get_cluster_offset(bs, offset, 1, 0, offset_in_cluster,
63
- qmp_object_add(args, &ret_data, &error_fatal);
60
+ offset_in_cluster + n, &cluster_offset);
64
+ user_creatable_add_dict(args, true, &error_fatal);
61
if (ret < 0) {
65
qobject_unref(args);
62
break;
66
- qobject_unref(ret_data);
63
}
64
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow_co_writev(BlockDriverState *bs, int64_t sector_num,
65
}
66
if (bs->encrypted) {
67
assert(s->crypto);
68
- if (qcrypto_block_encrypt(s->crypto, sector_num * BDRV_SECTOR_SIZE,
69
- buf, n * BDRV_SECTOR_SIZE, NULL) < 0) {
70
+ if (qcrypto_block_encrypt(s->crypto, offset, buf, n, NULL) < 0) {
71
ret = -EIO;
72
break;
67
break;
73
}
68
}
74
}
69
default:
75
70
diff --git a/qom/object_interfaces.c b/qom/object_interfaces.c
76
hd_iov.iov_base = (void *)buf;
71
index XXXXXXX..XXXXXXX 100644
77
- hd_iov.iov_len = n * 512;
72
--- a/qom/object_interfaces.c
78
+ hd_iov.iov_len = n;
73
+++ b/qom/object_interfaces.c
79
qemu_iovec_init_external(&hd_qiov, &hd_iov, 1);
74
@@ -XXX,XX +XXX,XX @@ out:
80
qemu_co_mutex_unlock(&s->lock);
75
return obj;
81
BLKDBG_EVENT(bs->file, BLKDBG_WRITE_AIO);
76
}
82
- ret = bdrv_co_writev(bs->file,
77
83
- (cluster_offset >> 9) + index_in_cluster,
78
-void user_creatable_add_dict(QDict *qdict, Error **errp)
84
- n, &hd_qiov);
79
+void user_creatable_add_dict(QDict *qdict, bool keyval, Error **errp)
85
+ ret = bdrv_co_pwritev(bs->file, cluster_offset + offset_in_cluster,
80
{
86
+ n, &hd_qiov, 0);
81
Visitor *v;
87
qemu_co_mutex_lock(&s->lock);
82
Object *obj;
88
if (ret < 0) {
83
@@ -XXX,XX +XXX,XX @@ void user_creatable_add_dict(QDict *qdict, Error **errp)
89
break;
90
}
91
ret = 0;
92
93
- nb_sectors -= n;
94
- sector_num += n;
95
- buf += n * 512;
96
+ bytes -= n;
97
+ offset += n;
98
+ buf += n;
99
}
84
}
100
qemu_co_mutex_unlock(&s->lock);
85
qdict_del(qdict, "id");
101
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)
102
--
109
--
103
2.13.6
110
2.25.3
104
111
105
112
diff view generated by jsdifflib