1
The following changes since commit 86f4c7e05b1c44dbe1b329a51f311f10aef6ff34:
1
The following changes since commit 16aaacb307ed607b9780c12702c44f0fe52edc7e:
2
2
3
Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20180302' into staging (2018-03-02 14:37:10 +0000)
3
Merge remote-tracking branch 'remotes/cohuck/tags/s390x-20200430' into staging (2020-04-30 14:00:36 +0100)
4
4
5
are available in the git repository at:
5
are available in the Git repository at:
6
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 9d9b4b640f9e583ff4b24dc762630945f3ccc16d:
9
for you to fetch changes up to eaae29ef89d498d0eac553c77b554f310a47f809:
10
10
11
Merge remote-tracking branch 'mreitz/tags/pull-block-2018-03-02' into queue-block (2018-03-02 18:45:03 +0100)
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
16
- Fix resize (extending) of short overlays
17
- nvme: introduce PMR support from NVMe 1.4 spec
18
- qemu-storage-daemon: Fix non-string --object properties
15
19
16
----------------------------------------------------------------
20
----------------------------------------------------------------
17
Alberto Garcia (3):
21
Alberto Garcia (1):
18
specs/qcow2: Fix documentation of the compressed cluster descriptor
22
qcow2: Add incompatibility note between backing files and raw external data files
19
docs: document how to use the l2-cache-entry-size parameter
20
qcow2: Replace align_offset() with ROUND_UP()
21
23
22
Anton Nefedov (2):
24
Andrzej Jakowski (1):
23
block: fix write with zero flag set and iovector provided
25
nvme: introduce PMR support from NVMe 1.4 spec
24
iotest 033: add misaligned write-zeroes test via truncate
25
26
26
Eric Blake (21):
27
Kevin Wolf (12):
27
block: Add .bdrv_co_block_status() callback
28
block: Add flags to BlockDriver.bdrv_co_truncate()
28
nvme: Drop pointless .bdrv_co_get_block_status()
29
block: Add flags to bdrv(_co)_truncate()
29
block: Switch passthrough drivers to .bdrv_co_block_status()
30
block-backend: Add flags to blk_truncate()
30
file-posix: Switch to .bdrv_co_block_status()
31
qcow2: Support BDRV_REQ_ZERO_WRITE for truncate
31
gluster: Switch to .bdrv_co_block_status()
32
raw-format: Support BDRV_REQ_ZERO_WRITE for truncate
32
iscsi: Switch cluster_sectors to byte-based
33
file-posix: Support BDRV_REQ_ZERO_WRITE for truncate
33
iscsi: Switch iscsi_allocmap_update() to byte-based
34
block: truncate: Don't make backing file data visible
34
iscsi: Switch to .bdrv_co_block_status()
35
iotests: Filter testfiles out in filter_img_info()
35
null: Switch to .bdrv_co_block_status()
36
iotests: Test committing to short backing file
36
parallels: Switch to .bdrv_co_block_status()
37
qcow2: Forward ZERO_WRITE flag for full preallocation
37
qcow: Switch to .bdrv_co_block_status()
38
qom: Factor out user_creatable_add_dict()
38
qcow2: Switch to .bdrv_co_block_status()
39
qemu-storage-daemon: Fix non-string --object properties
39
qed: Switch to .bdrv_co_block_status()
40
raw: Switch to .bdrv_co_block_status()
41
sheepdog: Switch to .bdrv_co_block_status()
42
vdi: Avoid bitrot of debugging code
43
vdi: Switch to .bdrv_co_block_status()
44
vmdk: Switch to .bdrv_co_block_status()
45
vpc: Switch to .bdrv_co_block_status()
46
vvfat: Switch to .bdrv_co_block_status()
47
block: Drop unused .bdrv_co_get_block_status()
48
40
49
Kevin Wolf (2):
41
Paolo Bonzini (1):
50
block: test blk_aio_flush() with blk->root == NULL
42
qemu-iotests: allow qcow2 external discarded clusters to contain stale data
51
Merge remote-tracking branch 'mreitz/tags/pull-block-2018-03-02' into queue-block
52
43
53
Max Reitz (4):
44
docs/interop/qcow2.txt | 3 +
54
qemu-img: Make resize error message more general
45
hw/block/nvme.h | 2 +
55
block/ssh: Pull ssh_grow_file() from ssh_create()
46
include/block/block.h | 5 +-
56
block/ssh: Make ssh_grow_file() blocking
47
include/block/block_int.h | 10 +-
57
block/ssh: Add basic .bdrv_truncate()
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
58
96
59
Stefan Hajnoczi (6):
60
aio: rename aio_context_in_iothread() to in_aio_context_home_thread()
61
block: extract AIO_WAIT_WHILE() from BlockDriverState
62
block: add BlockBackend->in_flight counter
63
Revert "IDE: Do not flush empty CDROM drives"
64
block: rename .bdrv_create() to .bdrv_co_create_opts()
65
qcow2: make qcow2_co_create2() a coroutine_fn
66
97
67
docs/interop/qcow2.txt | 16 ++++-
68
docs/qcow2-cache.txt | 46 ++++++++++++-
69
block/qcow2.h | 6 --
70
include/block/aio-wait.h | 116 ++++++++++++++++++++++++++++++++
71
include/block/aio.h | 7 +-
72
include/block/block.h | 54 ++++-----------
73
include/block/block_int.h | 61 ++++++++++-------
74
block.c | 11 ++-
75
block/blkdebug.c | 20 +++---
76
block/block-backend.c | 60 +++++++++++++++--
77
block/commit.c | 2 +-
78
block/crypto.c | 8 +--
79
block/file-posix.c | 79 +++++++++++-----------
80
block/file-win32.c | 5 +-
81
block/gluster.c | 83 ++++++++++++-----------
82
block/io.c | 98 +++++++++++----------------
83
block/iscsi.c | 164 ++++++++++++++++++++++++---------------------
84
block/mirror.c | 2 +-
85
block/nfs.c | 5 +-
86
block/null.c | 23 ++++---
87
block/nvme.c | 14 ----
88
block/parallels.c | 28 +++++---
89
block/qcow.c | 32 +++++----
90
block/qcow2-bitmap.c | 4 +-
91
block/qcow2-cluster.c | 4 +-
92
block/qcow2-refcount.c | 4 +-
93
block/qcow2-snapshot.c | 10 +--
94
block/qcow2.c | 60 +++++++++--------
95
block/qed.c | 82 ++++++++---------------
96
block/raw-format.c | 21 +++---
97
block/rbd.c | 6 +-
98
block/sheepdog.c | 36 +++++-----
99
block/ssh.c | 66 +++++++++++++++---
100
block/throttle.c | 2 +-
101
block/vdi.c | 50 +++++++-------
102
block/vhdx.c | 5 +-
103
block/vmdk.c | 43 +++++-------
104
block/vpc.c | 50 +++++++-------
105
block/vvfat.c | 16 ++---
106
hw/ide/core.c | 10 +--
107
qemu-img.c | 2 +-
108
tests/test-block-backend.c | 82 +++++++++++++++++++++++
109
util/aio-wait.c | 40 +++++++++++
110
tests/Makefile.include | 2 +
111
tests/qemu-iotests/033 | 29 ++++++++
112
tests/qemu-iotests/033.out | 13 ++++
113
util/Makefile.objs | 2 +-
114
47 files changed, 973 insertions(+), 606 deletions(-)
115
create mode 100644 include/block/aio-wait.h
116
create mode 100644 tests/test-block-backend.c
117
create mode 100644 util/aio-wait.c
118
diff view generated by jsdifflib
1
From: Alberto Garcia <berto@igalia.com>
1
From: Alberto Garcia <berto@igalia.com>
2
2
3
This patch fixes several mistakes in the documentation of the
3
Backing files and raw external data files are mutually exclusive.
4
compressed cluster descriptor:
4
The documentation of the raw external data bit (in autoclear_features)
5
already indicates that, but we should also mention it on the other
6
side.
5
7
6
1) the documentation claims that the cluster descriptor contains the
8
Suggested-by: Eric Blake <eblake@redhat.com>
7
number of sectors used to store the compressed data, but what it
8
actually contains is the number of sectors *minus one* or, in other
9
words, the number of additional sectors after the first one.
10
11
2) the width of the fields is incorrectly specified. The number of bits
12
used by each field is
13
14
x = 62 - (cluster_bits - 8) for the offset field
15
y = (cluster_bits - 8) for the size field
16
17
So the offset field's location is [0, x-1], not [0, x] as stated.
18
19
3) the size field does not contain the size of the compressed data,
20
but rather the number of sectors where that data is stored. The
21
compressed data starts at the exact point specified in the offset
22
field and ends when there's enough data to produce a cluster of
23
decompressed data. Both points can be in the middle of a sector,
24
allowing several compressed clusters to be stored next to one
25
another, sharing sectors if necessary.
26
27
Cc: qemu-stable@nongnu.org
28
Signed-off-by: Alberto Garcia <berto@igalia.com>
9
Signed-off-by: Alberto Garcia <berto@igalia.com>
10
Message-Id: <20200410121816.8334-1-berto@igalia.com>
29
Reviewed-by: Eric Blake <eblake@redhat.com>
11
Reviewed-by: Eric Blake <eblake@redhat.com>
30
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
31
---
13
---
32
docs/interop/qcow2.txt | 16 +++++++++++++---
14
docs/interop/qcow2.txt | 3 +++
33
1 file changed, 13 insertions(+), 3 deletions(-)
15
1 file changed, 3 insertions(+)
34
16
35
diff --git a/docs/interop/qcow2.txt b/docs/interop/qcow2.txt
17
diff --git a/docs/interop/qcow2.txt b/docs/interop/qcow2.txt
36
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
37
--- a/docs/interop/qcow2.txt
19
--- a/docs/interop/qcow2.txt
38
+++ b/docs/interop/qcow2.txt
20
+++ b/docs/interop/qcow2.txt
39
@@ -XXX,XX +XXX,XX @@ Standard Cluster Descriptor:
21
@@ -XXX,XX +XXX,XX @@ The first cluster of a qcow2 image contains the file header:
40
22
is stored (NB: The string is not null terminated). 0 if the
41
Compressed Clusters Descriptor (x = 62 - (cluster_bits - 8)):
23
image doesn't have a backing file.
42
24
43
- Bit 0 - x: Host cluster offset. This is usually _not_ aligned to a
25
+ Note: backing files are incompatible with raw external data
44
- cluster boundary!
26
+ files (auto-clear feature bit 1).
45
+ Bit 0 - x-1: Host cluster offset. This is usually _not_ aligned to a
46
+ cluster or sector boundary!
47
48
- x+1 - 61: Compressed size of the images in sectors of 512 bytes
49
+ x - 61: Number of additional 512-byte sectors used for the
50
+ compressed data, beyond the sector containing the offset
51
+ in the previous field. Some of these sectors may reside
52
+ in the next contiguous host cluster.
53
+
27
+
54
+ Note that the compressed data does not necessarily occupy
28
16 - 19: backing_file_size
55
+ all of the bytes in the final sector; rather, decompression
29
Length of the backing file name in bytes. Must not be
56
+ stops when it has produced a cluster of data.
30
longer than 1023 bytes. Undefined if the image doesn't have
57
+
58
+ Another compressed cluster may map to the tail of the final
59
+ sector used by this compressed cluster.
60
61
If a cluster is unallocated, read requests shall read the data from the backing
62
file (except if bit 0 in the Standard Cluster Descriptor is set). If there is
63
--
31
--
64
2.13.6
32
2.25.3
65
33
66
34
diff view generated by jsdifflib
1
From: Stefan Hajnoczi <stefanha@redhat.com>
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
2
3
qcow2_create2() calls qemu_co_mutex_lock(). Only a coroutine_fn may
3
Test 244 checks the expected behavior of qcow2 external data files
4
call another coroutine_fn. In fact, qcow2_create2 is always called from
4
with respect to zero and discarded clusters. Filesystems however
5
coroutine context.
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
Rename the function to add the "co" moniker and add coroutine_fn.
10
This fixes docker tests on RHEL8.
8
11
9
Reported-by: Marc-André Lureau <marcandre.lureau@redhat.com>
12
Cc: Kevin Wolf <kwolf@redhat.com>
10
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
13
Cc: qemu-block@nongnu.org
11
Message-Id: <20170705102231.20711-3-stefanha@redhat.com>
12
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
14
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
13
Reviewed-by: Eric Blake <eblake@redhat.com>
15
Message-Id: <20200409191006.24429-1-pbonzini@redhat.com>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
16
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
---
17
---
16
block/qcow2.c | 17 +++++++++--------
18
tests/qemu-iotests/244 | 10 ++++++++--
17
1 file changed, 9 insertions(+), 8 deletions(-)
19
tests/qemu-iotests/244.out | 9 ++++++---
20
2 files changed, 14 insertions(+), 5 deletions(-)
18
21
19
diff --git a/block/qcow2.c b/block/qcow2.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
20
index XXXXXXX..XXXXXXX 100644
52
index XXXXXXX..XXXXXXX 100644
21
--- a/block/qcow2.c
53
--- a/tests/qemu-iotests/244.out
22
+++ b/block/qcow2.c
54
+++ b/tests/qemu-iotests/244.out
23
@@ -XXX,XX +XXX,XX @@ static uint64_t qcow2_opt_get_refcount_bits_del(QemuOpts *opts, int version,
55
@@ -XXX,XX +XXX,XX @@ read 1048576/1048576 bytes at offset 0
24
return refcount_bits;
56
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
25
}
57
read 1048576/1048576 bytes at offset 1048576
26
58
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
27
-static int qcow2_create2(const char *filename, int64_t total_size,
59
-read 2097152/2097152 bytes at offset 2097152
28
- const char *backing_file, const char *backing_format,
60
-2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
29
- int flags, size_t cluster_size, PreallocMode prealloc,
61
read 1048576/1048576 bytes at offset 4194304
30
- QemuOpts *opts, int version, int refcount_order,
62
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
31
- const char *encryptfmt, Error **errp)
63
read 1048576/1048576 bytes at offset 5242880
32
+static int coroutine_fn
64
@@ -XXX,XX +XXX,XX @@ read 1048576/1048576 bytes at offset 1048576
33
+qcow2_co_create2(const char *filename, int64_t total_size,
65
read 4194304/4194304 bytes at offset 2097152
34
+ const char *backing_file, const char *backing_format,
66
4 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
35
+ int flags, size_t cluster_size, PreallocMode prealloc,
67
36
+ QemuOpts *opts, int version, int refcount_order,
68
-Images are identical.
37
+ const char *encryptfmt, Error **errp)
69
+read 1048576/1048576 bytes at offset 0
38
{
70
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
39
QDict *options;
71
+read 1048576/1048576 bytes at offset 1048576
40
72
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
41
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_create_opts(const char *filename, QemuOpts *opt
73
+read 3145728/3145728 bytes at offset 3145728
42
74
+3 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
43
refcount_order = ctz32(refcount_bits);
75
qcow2 file size after I/O: 327680
44
76
45
- ret = qcow2_create2(filename, size, backing_file, backing_fmt, flags,
77
=== bdrv_co_block_status test for file and offset=0 ===
46
- cluster_size, prealloc, opts, version, refcount_order,
47
- encryptfmt, &local_err);
48
+ ret = qcow2_co_create2(filename, size, backing_file, backing_fmt, flags,
49
+ cluster_size, prealloc, opts, version, refcount_order,
50
+ encryptfmt, &local_err);
51
error_propagate(errp, local_err);
52
53
finish:
54
--
78
--
55
2.13.6
79
2.25.3
56
80
57
81
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
1
This adds a new BdrvRequestFlags parameter to the .bdrv_co_truncate()
2
2
driver callbacks, and a supported_truncate_flags field in
3
We are gradually moving away from sector-based interfaces, towards
3
BlockDriverState that allows drivers to advertise support for request
4
byte-based. Now that all drivers have been updated to provide the
4
flags in the context of truncate.
5
byte-based .bdrv_co_block_status(), we can delete the sector-based
5
6
interface.
6
For now, we always pass 0 and no drivers declare support for any flag.
7
7
8
Signed-off-by: Eric Blake <eblake@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
9
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
10
Reviewed-by: Fam Zheng <famz@redhat.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>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
---
14
---
13
include/block/block_int.h | 3 ---
15
include/block/block_int.h | 10 +++++++++-
14
block/io.c | 50 ++++++++++-------------------------------------
16
block/crypto.c | 3 ++-
15
2 files changed, 10 insertions(+), 43 deletions(-)
17
block/file-posix.c | 2 +-
18
block/file-win32.c | 2 +-
19
block/gluster.c | 1 +
20
block/io.c | 8 +++++++-
21
block/iscsi.c | 2 +-
22
block/nfs.c | 3 ++-
23
block/qcow2.c | 2 +-
24
block/qed.c | 1 +
25
block/raw-format.c | 2 +-
26
block/rbd.c | 1 +
27
block/sheepdog.c | 4 ++--
28
block/ssh.c | 2 +-
29
tests/test-block-iothread.c | 3 ++-
30
15 files changed, 33 insertions(+), 13 deletions(-)
16
31
17
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
18
index XXXXXXX..XXXXXXX 100644
33
index XXXXXXX..XXXXXXX 100644
19
--- a/include/block/block_int.h
34
--- a/include/block/block_int.h
20
+++ b/include/block/block_int.h
35
+++ b/include/block/block_int.h
21
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
36
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
22
* as well as non-NULL pnum, map, and file; in turn, the driver
23
* must return an error or set pnum to an aligned non-zero value.
24
*/
37
*/
25
- int64_t coroutine_fn (*bdrv_co_get_block_status)(BlockDriverState *bs,
38
int coroutine_fn (*bdrv_co_truncate)(BlockDriverState *bs, int64_t offset,
26
- int64_t sector_num, int nb_sectors, int *pnum,
39
bool exact, PreallocMode prealloc,
27
- BlockDriverState **file);
40
- Error **errp);
28
int coroutine_fn (*bdrv_co_block_status)(BlockDriverState *bs,
41
+ BdrvRequestFlags flags, Error **errp);
29
bool want_zero, int64_t offset, int64_t bytes, int64_t *pnum,
42
30
int64_t *map, BlockDriverState **file);
43
int64_t (*bdrv_getlength)(BlockDriverState *bs);
44
bool has_variable_length;
45
@@ -XXX,XX +XXX,XX @@ struct BlockDriverState {
46
/* Flags honored during pwrite_zeroes (so far: BDRV_REQ_FUA,
47
* BDRV_REQ_MAY_UNMAP, BDRV_REQ_WRITE_UNCHANGED) */
48
unsigned int supported_zero_flags;
49
+ /*
50
+ * Flags honoured during truncate (so far: BDRV_REQ_ZERO_WRITE).
51
+ *
52
+ * If BDRV_REQ_ZERO_WRITE is given, the truncate operation must make sure
53
+ * that any added space reads as all zeros. If this can't be guaranteed,
54
+ * the operation must fail.
55
+ */
56
+ unsigned int supported_truncate_flags;
57
58
/* the following member gives a name to every node on the bs graph. */
59
char node_name[32];
60
diff --git a/block/crypto.c b/block/crypto.c
61
index XXXXXXX..XXXXXXX 100644
62
--- a/block/crypto.c
63
+++ b/block/crypto.c
64
@@ -XXX,XX +XXX,XX @@ static int block_crypto_co_create_generic(BlockDriverState *bs,
65
66
static int coroutine_fn
67
block_crypto_co_truncate(BlockDriverState *bs, int64_t offset, bool exact,
68
- PreallocMode prealloc, Error **errp)
69
+ PreallocMode prealloc, BdrvRequestFlags flags,
70
+ Error **errp)
71
{
72
BlockCrypto *crypto = bs->opaque;
73
uint64_t payload_offset =
74
diff --git a/block/file-posix.c b/block/file-posix.c
75
index XXXXXXX..XXXXXXX 100644
76
--- a/block/file-posix.c
77
+++ b/block/file-posix.c
78
@@ -XXX,XX +XXX,XX @@ raw_regular_truncate(BlockDriverState *bs, int fd, int64_t offset,
79
80
static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset,
81
bool exact, PreallocMode prealloc,
82
- Error **errp)
83
+ BdrvRequestFlags flags, Error **errp)
84
{
85
BDRVRawState *s = bs->opaque;
86
struct stat st;
87
diff --git a/block/file-win32.c b/block/file-win32.c
88
index XXXXXXX..XXXXXXX 100644
89
--- a/block/file-win32.c
90
+++ b/block/file-win32.c
91
@@ -XXX,XX +XXX,XX @@ static void raw_close(BlockDriverState *bs)
92
93
static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset,
94
bool exact, PreallocMode prealloc,
95
- Error **errp)
96
+ BdrvRequestFlags flags, Error **errp)
97
{
98
BDRVRawState *s = bs->opaque;
99
LONG low, high;
100
diff --git a/block/gluster.c b/block/gluster.c
101
index XXXXXXX..XXXXXXX 100644
102
--- a/block/gluster.c
103
+++ b/block/gluster.c
104
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qemu_gluster_co_truncate(BlockDriverState *bs,
105
int64_t offset,
106
bool exact,
107
PreallocMode prealloc,
108
+ BdrvRequestFlags flags,
109
Error **errp)
110
{
111
BDRVGlusterState *s = bs->opaque;
31
diff --git a/block/io.c b/block/io.c
112
diff --git a/block/io.c b/block/io.c
32
index XXXXXXX..XXXXXXX 100644
113
index XXXXXXX..XXXXXXX 100644
33
--- a/block/io.c
114
--- a/block/io.c
34
+++ b/block/io.c
115
+++ b/block/io.c
35
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_co_block_status(BlockDriverState *bs,
116
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
36
117
BlockDriverState *bs = child->bs;
37
/* Must be non-NULL or bdrv_getlength() would have failed */
118
BlockDriver *drv = bs->drv;
38
assert(bs->drv);
119
BdrvTrackedRequest req;
39
- if (!bs->drv->bdrv_co_get_block_status && !bs->drv->bdrv_co_block_status) {
120
+ BdrvRequestFlags flags = 0;
40
+ if (!bs->drv->bdrv_co_block_status) {
121
int64_t old_size, new_bytes;
41
*pnum = bytes;
122
int ret;
42
ret = BDRV_BLOCK_DATA | BDRV_BLOCK_ALLOCATED;
123
43
if (offset + bytes == total_size) {
124
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
44
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_co_block_status(BlockDriverState *bs,
45
46
/* Round out to request_alignment boundaries */
47
align = bs->bl.request_alignment;
48
- if (bs->drv->bdrv_co_get_block_status && align < BDRV_SECTOR_SIZE) {
49
- align = BDRV_SECTOR_SIZE;
50
- }
51
aligned_offset = QEMU_ALIGN_DOWN(offset, align);
52
aligned_bytes = ROUND_UP(offset + bytes, align) - aligned_offset;
53
54
- if (bs->drv->bdrv_co_get_block_status) {
55
- int count; /* sectors */
56
- int64_t longret;
57
-
58
- assert(QEMU_IS_ALIGNED(aligned_offset | aligned_bytes,
59
- BDRV_SECTOR_SIZE));
60
- /*
61
- * The contract allows us to return pnum smaller than bytes, even
62
- * if the next query would see the same status; we truncate the
63
- * request to avoid overflowing the driver's 32-bit interface.
64
- */
65
- longret = bs->drv->bdrv_co_get_block_status(
66
- bs, aligned_offset >> BDRV_SECTOR_BITS,
67
- MIN(INT_MAX, aligned_bytes) >> BDRV_SECTOR_BITS, &count,
68
- &local_file);
69
- if (longret < 0) {
70
- assert(INT_MIN <= longret);
71
- ret = longret;
72
- goto out;
73
- }
74
- if (longret & BDRV_BLOCK_OFFSET_VALID) {
75
- local_map = longret & BDRV_BLOCK_OFFSET_MASK;
76
- }
77
- ret = longret & ~BDRV_BLOCK_OFFSET_MASK;
78
- *pnum = count * BDRV_SECTOR_SIZE;
79
- } else {
80
- ret = bs->drv->bdrv_co_block_status(bs, want_zero, aligned_offset,
81
- aligned_bytes, pnum, &local_map,
82
- &local_file);
83
- if (ret < 0) {
84
- *pnum = 0;
85
- goto out;
86
- }
87
- assert(*pnum); /* The block driver must make progress */
88
+ ret = bs->drv->bdrv_co_block_status(bs, want_zero, aligned_offset,
89
+ aligned_bytes, pnum, &local_map,
90
+ &local_file);
91
+ if (ret < 0) {
92
+ *pnum = 0;
93
+ goto out;
94
}
125
}
95
126
96
/*
127
if (drv->bdrv_co_truncate) {
97
- * The driver's result must be a multiple of request_alignment.
128
- ret = drv->bdrv_co_truncate(bs, offset, exact, prealloc, errp);
98
+ * The driver's result must be a non-zero multiple of request_alignment.
129
+ if (flags & ~bs->supported_truncate_flags) {
99
* Clamp pnum and adjust map to original request.
130
+ error_setg(errp, "Block driver does not support requested flags");
100
*/
131
+ ret = -ENOTSUP;
101
- assert(QEMU_IS_ALIGNED(*pnum, align) && align > offset - aligned_offset);
132
+ goto out;
102
+ assert(*pnum && QEMU_IS_ALIGNED(*pnum, align) &&
133
+ }
103
+ align > offset - aligned_offset);
134
+ ret = drv->bdrv_co_truncate(bs, offset, exact, prealloc, flags, errp);
104
*pnum -= offset - aligned_offset;
135
} else if (bs->file && drv->is_filter) {
105
if (*pnum > bytes) {
136
ret = bdrv_co_truncate(bs->file, offset, exact, prealloc, errp);
106
*pnum = bytes;
137
} else {
138
diff --git a/block/iscsi.c b/block/iscsi.c
139
index XXXXXXX..XXXXXXX 100644
140
--- a/block/iscsi.c
141
+++ b/block/iscsi.c
142
@@ -XXX,XX +XXX,XX @@ static void iscsi_reopen_commit(BDRVReopenState *reopen_state)
143
144
static int coroutine_fn iscsi_co_truncate(BlockDriverState *bs, int64_t offset,
145
bool exact, PreallocMode prealloc,
146
- Error **errp)
147
+ BdrvRequestFlags flags, Error **errp)
148
{
149
IscsiLun *iscsilun = bs->opaque;
150
int64_t cur_length;
151
diff --git a/block/nfs.c b/block/nfs.c
152
index XXXXXXX..XXXXXXX 100644
153
--- a/block/nfs.c
154
+++ b/block/nfs.c
155
@@ -XXX,XX +XXX,XX @@ static int64_t nfs_get_allocated_file_size(BlockDriverState *bs)
156
157
static int coroutine_fn
158
nfs_file_co_truncate(BlockDriverState *bs, int64_t offset, bool exact,
159
- PreallocMode prealloc, Error **errp)
160
+ PreallocMode prealloc, BdrvRequestFlags flags,
161
+ Error **errp)
162
{
163
NFSClient *client = bs->opaque;
164
int ret;
165
diff --git a/block/qcow2.c b/block/qcow2.c
166
index XXXXXXX..XXXXXXX 100644
167
--- a/block/qcow2.c
168
+++ b/block/qcow2.c
169
@@ -XXX,XX +XXX,XX @@ fail:
170
171
static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
172
bool exact, PreallocMode prealloc,
173
- Error **errp)
174
+ BdrvRequestFlags flags, Error **errp)
175
{
176
BDRVQcow2State *s = bs->opaque;
177
uint64_t old_length;
178
diff --git a/block/qed.c b/block/qed.c
179
index XXXXXXX..XXXXXXX 100644
180
--- a/block/qed.c
181
+++ b/block/qed.c
182
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_qed_co_truncate(BlockDriverState *bs,
183
int64_t offset,
184
bool exact,
185
PreallocMode prealloc,
186
+ BdrvRequestFlags flags,
187
Error **errp)
188
{
189
BDRVQEDState *s = bs->opaque;
190
diff --git a/block/raw-format.c b/block/raw-format.c
191
index XXXXXXX..XXXXXXX 100644
192
--- a/block/raw-format.c
193
+++ b/block/raw-format.c
194
@@ -XXX,XX +XXX,XX @@ static void raw_refresh_limits(BlockDriverState *bs, Error **errp)
195
196
static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset,
197
bool exact, PreallocMode prealloc,
198
- Error **errp)
199
+ BdrvRequestFlags flags, Error **errp)
200
{
201
BDRVRawState *s = bs->opaque;
202
203
diff --git a/block/rbd.c b/block/rbd.c
204
index XXXXXXX..XXXXXXX 100644
205
--- a/block/rbd.c
206
+++ b/block/rbd.c
207
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qemu_rbd_co_truncate(BlockDriverState *bs,
208
int64_t offset,
209
bool exact,
210
PreallocMode prealloc,
211
+ BdrvRequestFlags flags,
212
Error **errp)
213
{
214
int r;
215
diff --git a/block/sheepdog.c b/block/sheepdog.c
216
index XXXXXXX..XXXXXXX 100644
217
--- a/block/sheepdog.c
218
+++ b/block/sheepdog.c
219
@@ -XXX,XX +XXX,XX @@ static int64_t sd_getlength(BlockDriverState *bs)
220
221
static int coroutine_fn sd_co_truncate(BlockDriverState *bs, int64_t offset,
222
bool exact, PreallocMode prealloc,
223
- Error **errp)
224
+ BdrvRequestFlags flags, Error **errp)
225
{
226
BDRVSheepdogState *s = bs->opaque;
227
int ret, fd;
228
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int sd_co_writev(BlockDriverState *bs, int64_t sector_num,
229
230
assert(!flags);
231
if (offset > s->inode.vdi_size) {
232
- ret = sd_co_truncate(bs, offset, false, PREALLOC_MODE_OFF, NULL);
233
+ ret = sd_co_truncate(bs, offset, false, PREALLOC_MODE_OFF, 0, NULL);
234
if (ret < 0) {
235
return ret;
236
}
237
diff --git a/block/ssh.c b/block/ssh.c
238
index XXXXXXX..XXXXXXX 100644
239
--- a/block/ssh.c
240
+++ b/block/ssh.c
241
@@ -XXX,XX +XXX,XX @@ static int64_t ssh_getlength(BlockDriverState *bs)
242
243
static int coroutine_fn ssh_co_truncate(BlockDriverState *bs, int64_t offset,
244
bool exact, PreallocMode prealloc,
245
- Error **errp)
246
+ BdrvRequestFlags flags, Error **errp)
247
{
248
BDRVSSHState *s = bs->opaque;
249
250
diff --git a/tests/test-block-iothread.c b/tests/test-block-iothread.c
251
index XXXXXXX..XXXXXXX 100644
252
--- a/tests/test-block-iothread.c
253
+++ b/tests/test-block-iothread.c
254
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_test_co_pdiscard(BlockDriverState *bs,
255
256
static int coroutine_fn
257
bdrv_test_co_truncate(BlockDriverState *bs, int64_t offset, bool exact,
258
- PreallocMode prealloc, Error **errp)
259
+ PreallocMode prealloc, BdrvRequestFlags flags,
260
+ Error **errp)
261
{
262
return 0;
263
}
107
--
264
--
108
2.13.6
265
2.25.3
109
266
110
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 the block layer exposes byte-based allocation,
5
it's time to tackle the drivers. Add a new callback that operates
6
on as small as byte boundaries. Subsequent patches will then update
7
individual drivers, then finally remove .bdrv_co_get_block_status().
8
9
The new code also passes through the 'want_zero' hint, which will
10
allow subsequent patches to further optimize callers that only care
11
about how much of the image is allocated (want_zero is false),
12
rather than full details about runs of zeroes and which offsets the
13
allocation actually maps to (want_zero is true). As part of this
14
effort, fix another part of the documentation: the claim in commit
15
4c41cb4 that BDRV_BLOCK_ALLOCATED is short for 'DATA || ZERO' is a
16
lie at the block layer (see commit e88ae2264), even though it is
17
how the bit is computed from the driver layer. After all, there
18
are intentionally cases where we return ZERO but not ALLOCATED at
19
the block layer, when we know that a read sees zero because the
20
backing file is too short. Note that the driver interface is thus
21
slightly different than the public interface with regards to which
22
bits will be set, and what guarantees are provided on input.
23
24
We also add an assertion that any driver using the new callback will
25
make progress (the only time pnum will be 0 is if the block layer
26
already handled an out-of-bounds request, or if there is an error);
27
the old driver interface did not provide this guarantee, which
28
could lead to some inf-loops in drastic corner-case failures.
29
30
Signed-off-by: Eric Blake <eblake@redhat.com>
31
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
6
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
32
Reviewed-by: Fam Zheng <famz@redhat.com>
7
Reviewed-by: Alberto Garcia <berto@igalia.com>
8
Reviewed-by: Max Reitz <mreitz@redhat.com>
9
Message-Id: <20200424125448.63318-3-kwolf@redhat.com>
33
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
34
---
11
---
35
include/block/block.h | 14 +++++++-------
12
include/block/block.h | 5 +++--
36
include/block/block_int.h | 20 +++++++++++++++-----
13
block/block-backend.c | 2 +-
37
block/io.c | 28 +++++++++++++++++++---------
14
block/crypto.c | 2 +-
38
3 files changed, 41 insertions(+), 21 deletions(-)
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(-)
39
26
40
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
41
index XXXXXXX..XXXXXXX 100644
28
index XXXXXXX..XXXXXXX 100644
42
--- a/include/block/block.h
29
--- a/include/block/block.h
43
+++ b/include/block/block.h
30
+++ b/include/block/block.h
44
@@ -XXX,XX +XXX,XX @@ typedef struct HDGeometry {
31
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs,
45
* BDRV_BLOCK_ZERO: offset reads as zero
32
void bdrv_refresh_filename(BlockDriverState *bs);
46
* BDRV_BLOCK_OFFSET_VALID: an associated offset exists for accessing raw data
33
47
* BDRV_BLOCK_ALLOCATED: the content of the block is determined by this
34
int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
48
- * layer (short for DATA || ZERO), set by block layer
35
- PreallocMode prealloc, Error **errp);
49
- * BDRV_BLOCK_EOF: the returned pnum covers through end of file for this layer
36
+ PreallocMode prealloc, BdrvRequestFlags flags,
50
+ * layer rather than any backing, set by block layer
37
+ Error **errp);
51
+ * BDRV_BLOCK_EOF: the returned pnum covers through end of file for this
38
int bdrv_truncate(BdrvChild *child, int64_t offset, bool exact,
52
+ * layer, set by block layer
39
- PreallocMode prealloc, Error **errp);
53
*
40
+ PreallocMode prealloc, BdrvRequestFlags flags, Error **errp);
54
* Internal flag:
41
55
* BDRV_BLOCK_RAW: for use by passthrough drivers, such as raw, to request
42
int64_t bdrv_nb_sectors(BlockDriverState *bs);
56
* that the block layer recompute the answer from the returned
43
int64_t bdrv_getlength(BlockDriverState *bs);
57
* BDS; must be accompanied by just BDRV_BLOCK_OFFSET_VALID.
44
diff --git a/block/block-backend.c b/block/block-backend.c
58
*
45
index XXXXXXX..XXXXXXX 100644
59
- * If BDRV_BLOCK_OFFSET_VALID is set, bits 9-62 (BDRV_BLOCK_OFFSET_MASK) of
46
--- a/block/block-backend.c
60
- * the return value (old interface) or the entire map parameter (new
47
+++ b/block/block-backend.c
61
- * interface) represent the offset in the returned BDS that is allocated for
48
@@ -XXX,XX +XXX,XX @@ int blk_truncate(BlockBackend *blk, int64_t offset, bool exact,
62
- * the corresponding raw data. However, whether that offset actually
49
return -ENOMEDIUM;
63
- * contains data also depends on BDRV_BLOCK_DATA, as follows:
50
}
64
+ * If BDRV_BLOCK_OFFSET_VALID is set, the map parameter represents the
51
65
+ * host offset within the returned BDS that is allocated for the
52
- return bdrv_truncate(blk->root, offset, exact, prealloc, errp);
66
+ * corresponding raw guest data. However, whether that offset
53
+ return bdrv_truncate(blk->root, offset, exact, prealloc, 0, errp);
67
+ * actually contains data also depends on BDRV_BLOCK_DATA, as follows:
54
}
68
*
55
69
* DATA ZERO OFFSET_VALID
56
int blk_save_vmstate(BlockBackend *blk, const uint8_t *buf,
70
* t t t sectors read as zero, returned file is zero at offset
57
diff --git a/block/crypto.c b/block/crypto.c
71
diff --git a/include/block/block_int.h b/include/block/block_int.h
58
index XXXXXXX..XXXXXXX 100644
72
index XXXXXXX..XXXXXXX 100644
59
--- a/block/crypto.c
73
--- a/include/block/block_int.h
60
+++ b/block/crypto.c
74
+++ b/include/block/block_int.h
61
@@ -XXX,XX +XXX,XX @@ block_crypto_co_truncate(BlockDriverState *bs, int64_t offset, bool exact,
75
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
62
76
/*
63
offset += payload_offset;
77
* Building block for bdrv_block_status[_above] and
64
78
* bdrv_is_allocated[_above]. The driver should answer only
65
- return bdrv_co_truncate(bs->file, offset, exact, prealloc, errp);
79
- * according to the current layer, and should not set
66
+ return bdrv_co_truncate(bs->file, offset, exact, prealloc, 0, errp);
80
- * BDRV_BLOCK_ALLOCATED, but may set BDRV_BLOCK_RAW. See block.h
67
}
81
- * for the meaning of _DATA, _ZERO, and _OFFSET_VALID. The block
68
82
- * layer guarantees input aligned to request_alignment, as well as
69
static void block_crypto_close(BlockDriverState *bs)
83
- * non-NULL pnum and file.
84
+ * according to the current layer, and should only need to set
85
+ * BDRV_BLOCK_DATA, BDRV_BLOCK_ZERO, BDRV_BLOCK_OFFSET_VALID,
86
+ * and/or BDRV_BLOCK_RAW; if the current layer defers to a backing
87
+ * layer, the result should be 0 (and not BDRV_BLOCK_ZERO). See
88
+ * block.h for the overall meaning of the bits. As a hint, the
89
+ * flag want_zero is true if the caller cares more about precise
90
+ * mappings (favor accurate _OFFSET_VALID/_ZERO) or false for
91
+ * overall allocation (favor larger *pnum, perhaps by reporting
92
+ * _DATA instead of _ZERO). The block layer guarantees input
93
+ * clamped to bdrv_getlength() and aligned to request_alignment,
94
+ * as well as non-NULL pnum, map, and file; in turn, the driver
95
+ * must return an error or set pnum to an aligned non-zero value.
96
*/
97
int64_t coroutine_fn (*bdrv_co_get_block_status)(BlockDriverState *bs,
98
int64_t sector_num, int nb_sectors, int *pnum,
99
BlockDriverState **file);
100
+ int coroutine_fn (*bdrv_co_block_status)(BlockDriverState *bs,
101
+ bool want_zero, int64_t offset, int64_t bytes, int64_t *pnum,
102
+ int64_t *map, BlockDriverState **file);
103
104
/*
105
* Invalidate any cached meta-data.
106
diff --git a/block/io.c b/block/io.c
70
diff --git a/block/io.c b/block/io.c
107
index XXXXXXX..XXXXXXX 100644
71
index XXXXXXX..XXXXXXX 100644
108
--- a/block/io.c
72
--- a/block/io.c
109
+++ b/block/io.c
73
+++ b/block/io.c
110
@@ -XXX,XX +XXX,XX @@ int64_t coroutine_fn bdrv_co_get_block_status_from_backing(BlockDriverState *bs,
74
@@ -XXX,XX +XXX,XX @@ static void bdrv_parent_cb_resize(BlockDriverState *bs)
111
* Drivers not implementing the functionality are assumed to not support
75
* 'offset' bytes in length.
112
* backing files, hence all their sectors are reported as allocated.
76
*/
113
*
77
int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
114
- * If 'want_zero' is true, the caller is querying for mapping purposes,
78
- PreallocMode prealloc, Error **errp)
115
- * and the result should include BDRV_BLOCK_OFFSET_VALID and
79
+ PreallocMode prealloc, BdrvRequestFlags flags,
116
- * BDRV_BLOCK_ZERO where possible; otherwise, the result may omit those
80
+ Error **errp)
117
- * bits particularly if it allows for a larger value in 'pnum'.
81
{
118
+ * If 'want_zero' is true, the caller is querying for mapping
82
BlockDriverState *bs = child->bs;
119
+ * purposes, with a focus on valid BDRV_BLOCK_OFFSET_VALID, _DATA, and
83
BlockDriver *drv = bs->drv;
120
+ * _ZERO where possible; otherwise, the result favors larger 'pnum',
84
BdrvTrackedRequest req;
121
+ * with a focus on accurate BDRV_BLOCK_ALLOCATED.
85
- BdrvRequestFlags flags = 0;
122
*
86
int64_t old_size, new_bytes;
123
* If 'offset' is beyond the end of the disk image the return value is
87
int ret;
124
* BDRV_BLOCK_EOF and 'pnum' is set to 0.
88
125
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_co_block_status(BlockDriverState *bs,
89
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
126
90
}
127
/* Must be non-NULL or bdrv_getlength() would have failed */
91
ret = drv->bdrv_co_truncate(bs, offset, exact, prealloc, flags, errp);
128
assert(bs->drv);
92
} else if (bs->file && drv->is_filter) {
129
- if (!bs->drv->bdrv_co_get_block_status) {
93
- ret = bdrv_co_truncate(bs->file, offset, exact, prealloc, errp);
130
+ if (!bs->drv->bdrv_co_get_block_status && !bs->drv->bdrv_co_block_status) {
94
+ ret = bdrv_co_truncate(bs->file, offset, exact, prealloc, flags, errp);
131
*pnum = bytes;
95
} else {
132
ret = BDRV_BLOCK_DATA | BDRV_BLOCK_ALLOCATED;
96
error_setg(errp, "Image format driver does not support resize");
133
if (offset + bytes == total_size) {
97
ret = -ENOTSUP;
134
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_co_block_status(BlockDriverState *bs,
98
@@ -XXX,XX +XXX,XX @@ typedef struct TruncateCo {
135
bdrv_inc_in_flight(bs);
99
int64_t offset;
136
100
bool exact;
137
/* Round out to request_alignment boundaries */
101
PreallocMode prealloc;
138
- /* TODO: until we have a byte-based driver callback, we also have to
102
+ BdrvRequestFlags flags;
139
- * round out to sectors, even if that is bigger than request_alignment */
103
Error **errp;
140
- align = MAX(bs->bl.request_alignment, BDRV_SECTOR_SIZE);
104
int ret;
141
+ align = bs->bl.request_alignment;
105
} TruncateCo;
142
+ if (bs->drv->bdrv_co_get_block_status && align < BDRV_SECTOR_SIZE) {
106
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn bdrv_truncate_co_entry(void *opaque)
143
+ align = BDRV_SECTOR_SIZE;
107
{
144
+ }
108
TruncateCo *tco = opaque;
145
aligned_offset = QEMU_ALIGN_DOWN(offset, align);
109
tco->ret = bdrv_co_truncate(tco->child, tco->offset, tco->exact,
146
aligned_bytes = ROUND_UP(offset + bytes, align) - aligned_offset;
110
- tco->prealloc, tco->errp);
147
111
+ tco->prealloc, tco->flags, tco->errp);
148
- {
112
aio_wait_kick();
149
+ if (bs->drv->bdrv_co_get_block_status) {
113
}
150
int count; /* sectors */
114
151
int64_t longret;
115
int bdrv_truncate(BdrvChild *child, int64_t offset, bool exact,
152
116
- PreallocMode prealloc, Error **errp)
153
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_co_block_status(BlockDriverState *bs,
117
+ PreallocMode prealloc, BdrvRequestFlags flags, Error **errp)
154
}
118
{
155
ret = longret & ~BDRV_BLOCK_OFFSET_MASK;
119
Coroutine *co;
156
*pnum = count * BDRV_SECTOR_SIZE;
120
TruncateCo tco = {
157
+ } else {
121
@@ -XXX,XX +XXX,XX @@ int bdrv_truncate(BdrvChild *child, int64_t offset, bool exact,
158
+ ret = bs->drv->bdrv_co_block_status(bs, want_zero, aligned_offset,
122
.offset = offset,
159
+ aligned_bytes, pnum, &local_map,
123
.exact = exact,
160
+ &local_file);
124
.prealloc = prealloc,
161
+ if (ret < 0) {
125
+ .flags = flags,
162
+ *pnum = 0;
126
.errp = errp,
163
+ goto out;
127
.ret = NOT_DONE,
164
+ }
128
};
165
+ assert(*pnum); /* The block driver must make progress */
129
diff --git a/block/parallels.c b/block/parallels.c
166
}
130
index XXXXXXX..XXXXXXX 100644
167
131
--- a/block/parallels.c
168
/*
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;
169
--
334
--
170
2.13.6
335
2.25.3
171
336
172
337
diff view generated by jsdifflib
Deleted patch
1
From: Eric Blake <eblake@redhat.com>
2
1
3
Commit bdd6a90 has a bug: drivers should never directly set
4
BDRV_BLOCK_ALLOCATED, but only io.c should do that (as needed).
5
Instead, drivers should report BDRV_BLOCK_DATA if it knows that
6
data comes from this BDS.
7
8
But let's look at the bigger picture: semantically, the nvme
9
driver is similar to the nbd, null, and raw drivers (no backing
10
file, all data comes from this BDS). But while two of those
11
other drivers have to supply the callback (null because it can
12
special-case BDRV_BLOCK_ZERO, raw because it can special-case
13
a different offset), in this case the block layer defaults are
14
good enough without the callback at all (similar to nbd).
15
16
So, fix the bug by deletion ;)
17
18
Signed-off-by: Eric Blake <eblake@redhat.com>
19
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
20
---
21
block/nvme.c | 14 --------------
22
1 file changed, 14 deletions(-)
23
24
diff --git a/block/nvme.c b/block/nvme.c
25
index XXXXXXX..XXXXXXX 100644
26
--- a/block/nvme.c
27
+++ b/block/nvme.c
28
@@ -XXX,XX +XXX,XX @@ static int nvme_reopen_prepare(BDRVReopenState *reopen_state,
29
return 0;
30
}
31
32
-static int64_t coroutine_fn nvme_co_get_block_status(BlockDriverState *bs,
33
- int64_t sector_num,
34
- int nb_sectors, int *pnum,
35
- BlockDriverState **file)
36
-{
37
- *pnum = nb_sectors;
38
- *file = bs;
39
-
40
- return BDRV_BLOCK_ALLOCATED | BDRV_BLOCK_OFFSET_VALID |
41
- (sector_num << BDRV_SECTOR_BITS);
42
-}
43
-
44
static void nvme_refresh_filename(BlockDriverState *bs, QDict *opts)
45
{
46
QINCREF(opts);
47
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_nvme = {
48
.bdrv_co_flush_to_disk = nvme_co_flush,
49
.bdrv_reopen_prepare = nvme_reopen_prepare,
50
51
- .bdrv_co_get_block_status = nvme_co_get_block_status,
52
-
53
.bdrv_refresh_filename = nvme_refresh_filename,
54
.bdrv_refresh_limits = nvme_refresh_limits,
55
56
--
57
2.13.6
58
59
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. Update the generic helpers, and all passthrough clients
5
(blkdebug, commit, mirror, throttle) accordingly.
6
7
Signed-off-by: Eric Blake <eblake@redhat.com>
8
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
9
Reviewed-by: Fam Zheng <famz@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
---
12
include/block/block_int.h | 28 ++++++++++++++++------------
13
block/blkdebug.c | 20 +++++++++++---------
14
block/commit.c | 2 +-
15
block/io.c | 36 ++++++++++++++++++++----------------
16
block/mirror.c | 2 +-
17
block/throttle.c | 2 +-
18
6 files changed, 50 insertions(+), 40 deletions(-)
19
20
diff --git a/include/block/block_int.h b/include/block/block_int.h
21
index XXXXXXX..XXXXXXX 100644
22
--- a/include/block/block_int.h
23
+++ b/include/block/block_int.h
24
@@ -XXX,XX +XXX,XX @@ void bdrv_format_default_perms(BlockDriverState *bs, BdrvChild *c,
25
uint64_t *nperm, uint64_t *nshared);
26
27
/*
28
- * Default implementation for drivers to pass bdrv_co_get_block_status() to
29
+ * Default implementation for drivers to pass bdrv_co_block_status() to
30
* their file.
31
*/
32
-int64_t coroutine_fn bdrv_co_get_block_status_from_file(BlockDriverState *bs,
33
- int64_t sector_num,
34
- int nb_sectors,
35
- int *pnum,
36
- BlockDriverState **file);
37
+int coroutine_fn bdrv_co_block_status_from_file(BlockDriverState *bs,
38
+ bool want_zero,
39
+ int64_t offset,
40
+ int64_t bytes,
41
+ int64_t *pnum,
42
+ int64_t *map,
43
+ BlockDriverState **file);
44
/*
45
- * Default implementation for drivers to pass bdrv_co_get_block_status() to
46
+ * Default implementation for drivers to pass bdrv_co_block_status() to
47
* their backing file.
48
*/
49
-int64_t coroutine_fn bdrv_co_get_block_status_from_backing(BlockDriverState *bs,
50
- int64_t sector_num,
51
- int nb_sectors,
52
- int *pnum,
53
- BlockDriverState **file);
54
+int coroutine_fn bdrv_co_block_status_from_backing(BlockDriverState *bs,
55
+ bool want_zero,
56
+ int64_t offset,
57
+ int64_t bytes,
58
+ int64_t *pnum,
59
+ int64_t *map,
60
+ BlockDriverState **file);
61
const char *bdrv_get_parent_name(const BlockDriverState *bs);
62
void blk_dev_change_media_cb(BlockBackend *blk, bool load, Error **errp);
63
bool blk_dev_has_removable_media(BlockBackend *blk);
64
diff --git a/block/blkdebug.c b/block/blkdebug.c
65
index XXXXXXX..XXXXXXX 100644
66
--- a/block/blkdebug.c
67
+++ b/block/blkdebug.c
68
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn blkdebug_co_pdiscard(BlockDriverState *bs,
69
return bdrv_co_pdiscard(bs->file->bs, offset, bytes);
70
}
71
72
-static int64_t coroutine_fn blkdebug_co_get_block_status(
73
- BlockDriverState *bs, int64_t sector_num, int nb_sectors, int *pnum,
74
- BlockDriverState **file)
75
+static int coroutine_fn blkdebug_co_block_status(BlockDriverState *bs,
76
+ bool want_zero,
77
+ int64_t offset,
78
+ int64_t bytes,
79
+ int64_t *pnum,
80
+ int64_t *map,
81
+ BlockDriverState **file)
82
{
83
- assert(QEMU_IS_ALIGNED(sector_num | nb_sectors,
84
- DIV_ROUND_UP(bs->bl.request_alignment,
85
- BDRV_SECTOR_SIZE)));
86
- return bdrv_co_get_block_status_from_file(bs, sector_num, nb_sectors,
87
- pnum, file);
88
+ assert(QEMU_IS_ALIGNED(offset | bytes, bs->bl.request_alignment));
89
+ return bdrv_co_block_status_from_file(bs, want_zero, offset, bytes,
90
+ pnum, map, file);
91
}
92
93
static void blkdebug_close(BlockDriverState *bs)
94
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_blkdebug = {
95
.bdrv_co_flush_to_disk = blkdebug_co_flush,
96
.bdrv_co_pwrite_zeroes = blkdebug_co_pwrite_zeroes,
97
.bdrv_co_pdiscard = blkdebug_co_pdiscard,
98
- .bdrv_co_get_block_status = blkdebug_co_get_block_status,
99
+ .bdrv_co_block_status = blkdebug_co_block_status,
100
101
.bdrv_debug_event = blkdebug_debug_event,
102
.bdrv_debug_breakpoint = blkdebug_debug_breakpoint,
103
diff --git a/block/commit.c b/block/commit.c
104
index XXXXXXX..XXXXXXX 100644
105
--- a/block/commit.c
106
+++ b/block/commit.c
107
@@ -XXX,XX +XXX,XX @@ static void bdrv_commit_top_child_perm(BlockDriverState *bs, BdrvChild *c,
108
static BlockDriver bdrv_commit_top = {
109
.format_name = "commit_top",
110
.bdrv_co_preadv = bdrv_commit_top_preadv,
111
- .bdrv_co_get_block_status = bdrv_co_get_block_status_from_backing,
112
+ .bdrv_co_block_status = bdrv_co_block_status_from_backing,
113
.bdrv_refresh_filename = bdrv_commit_top_refresh_filename,
114
.bdrv_close = bdrv_commit_top_close,
115
.bdrv_child_perm = bdrv_commit_top_child_perm,
116
diff --git a/block/io.c b/block/io.c
117
index XXXXXXX..XXXXXXX 100644
118
--- a/block/io.c
119
+++ b/block/io.c
120
@@ -XXX,XX +XXX,XX @@ typedef struct BdrvCoBlockStatusData {
121
bool done;
122
} BdrvCoBlockStatusData;
123
124
-int64_t coroutine_fn bdrv_co_get_block_status_from_file(BlockDriverState *bs,
125
- int64_t sector_num,
126
- int nb_sectors,
127
- int *pnum,
128
- BlockDriverState **file)
129
+int coroutine_fn bdrv_co_block_status_from_file(BlockDriverState *bs,
130
+ bool want_zero,
131
+ int64_t offset,
132
+ int64_t bytes,
133
+ int64_t *pnum,
134
+ int64_t *map,
135
+ BlockDriverState **file)
136
{
137
assert(bs->file && bs->file->bs);
138
- *pnum = nb_sectors;
139
+ *pnum = bytes;
140
+ *map = offset;
141
*file = bs->file->bs;
142
- return BDRV_BLOCK_RAW | BDRV_BLOCK_OFFSET_VALID |
143
- (sector_num << BDRV_SECTOR_BITS);
144
+ return BDRV_BLOCK_RAW | BDRV_BLOCK_OFFSET_VALID;
145
}
146
147
-int64_t coroutine_fn bdrv_co_get_block_status_from_backing(BlockDriverState *bs,
148
- int64_t sector_num,
149
- int nb_sectors,
150
- int *pnum,
151
- BlockDriverState **file)
152
+int coroutine_fn bdrv_co_block_status_from_backing(BlockDriverState *bs,
153
+ bool want_zero,
154
+ int64_t offset,
155
+ int64_t bytes,
156
+ int64_t *pnum,
157
+ int64_t *map,
158
+ BlockDriverState **file)
159
{
160
assert(bs->backing && bs->backing->bs);
161
- *pnum = nb_sectors;
162
+ *pnum = bytes;
163
+ *map = offset;
164
*file = bs->backing->bs;
165
- return BDRV_BLOCK_RAW | BDRV_BLOCK_OFFSET_VALID |
166
- (sector_num << BDRV_SECTOR_BITS);
167
+ return BDRV_BLOCK_RAW | BDRV_BLOCK_OFFSET_VALID;
168
}
169
170
/*
171
diff --git a/block/mirror.c b/block/mirror.c
172
index XXXXXXX..XXXXXXX 100644
173
--- a/block/mirror.c
174
+++ b/block/mirror.c
175
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_mirror_top = {
176
.bdrv_co_pwrite_zeroes = bdrv_mirror_top_pwrite_zeroes,
177
.bdrv_co_pdiscard = bdrv_mirror_top_pdiscard,
178
.bdrv_co_flush = bdrv_mirror_top_flush,
179
- .bdrv_co_get_block_status = bdrv_co_get_block_status_from_backing,
180
+ .bdrv_co_block_status = bdrv_co_block_status_from_backing,
181
.bdrv_refresh_filename = bdrv_mirror_top_refresh_filename,
182
.bdrv_close = bdrv_mirror_top_close,
183
.bdrv_child_perm = bdrv_mirror_top_child_perm,
184
diff --git a/block/throttle.c b/block/throttle.c
185
index XXXXXXX..XXXXXXX 100644
186
--- a/block/throttle.c
187
+++ b/block/throttle.c
188
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_throttle = {
189
.bdrv_reopen_prepare = throttle_reopen_prepare,
190
.bdrv_reopen_commit = throttle_reopen_commit,
191
.bdrv_reopen_abort = throttle_reopen_abort,
192
- .bdrv_co_get_block_status = bdrv_co_get_block_status_from_file,
193
+ .bdrv_co_block_status = bdrv_co_block_status_from_file,
194
195
.bdrv_co_drain_begin = throttle_co_drain_begin,
196
.bdrv_co_drain_end = throttle_co_drain_end,
197
--
198
2.13.6
199
200
diff view generated by jsdifflib
1
From: Stefan Hajnoczi <stefanha@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
BlockDriver->bdrv_create() has been called from coroutine context since
3
4
commit 5b7e1542cfa41a281af9629d31cef03704d976e6 ("block: make
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
bdrv_create adopt coroutine").
5
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
6
6
Reviewed-by: Alberto Garcia <berto@igalia.com>
7
Make this explicit by renaming to .bdrv_co_create_opts() and add the
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
8
coroutine_fn annotation. This makes it obvious to block driver authors
8
Message-Id: <20200424125448.63318-4-kwolf@redhat.com>
9
that they may yield, use CoMutex, or other coroutine_fn APIs.
10
bdrv_co_create is reserved for the QAPI-based version that Kevin is
11
working on.
12
13
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
14
Message-Id: <20170705102231.20711-2-stefanha@redhat.com>
15
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
16
Reviewed-by: Eric Blake <eblake@redhat.com>
17
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
18
---
10
---
19
include/block/block_int.h | 3 ++-
11
include/sysemu/block-backend.h | 2 +-
20
block.c | 4 ++--
12
block.c | 3 ++-
21
block/crypto.c | 8 ++++----
13
block/block-backend.c | 4 ++--
22
block/file-posix.c | 15 ++++++++-------
14
block/commit.c | 4 ++--
23
block/file-win32.c | 5 +++--
15
block/crypto.c | 2 +-
24
block/gluster.c | 13 +++++++------
16
block/mirror.c | 2 +-
25
block/iscsi.c | 7 ++++---
17
block/qcow2.c | 4 ++--
26
block/nfs.c | 5 +++--
18
block/qed.c | 2 +-
27
block/parallels.c | 6 ++++--
19
block/vdi.c | 2 +-
28
block/qcow.c | 5 +++--
20
block/vhdx.c | 4 ++--
29
block/qcow2.c | 5 +++--
21
block/vmdk.c | 6 +++---
30
block/qed.c | 6 ++++--
22
block/vpc.c | 2 +-
31
block/raw-format.c | 5 +++--
23
blockdev.c | 2 +-
32
block/rbd.c | 6 ++++--
24
qemu-img.c | 2 +-
33
block/sheepdog.c | 10 +++++-----
25
qemu-io-cmds.c | 2 +-
34
block/ssh.c | 5 +++--
26
15 files changed, 22 insertions(+), 21 deletions(-)
35
block/vdi.c | 5 +++--
27
36
block/vhdx.c | 5 +++--
28
diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h
37
block/vmdk.c | 5 +++--
29
index XXXXXXX..XXXXXXX 100644
38
block/vpc.c | 5 +++--
30
--- a/include/sysemu/block-backend.h
39
20 files changed, 74 insertions(+), 54 deletions(-)
31
+++ b/include/sysemu/block-backend.h
40
32
@@ -XXX,XX +XXX,XX @@ int coroutine_fn blk_co_pwrite_zeroes(BlockBackend *blk, int64_t offset,
41
diff --git a/include/block/block_int.h b/include/block/block_int.h
33
int blk_pwrite_compressed(BlockBackend *blk, int64_t offset, const void *buf,
42
index XXXXXXX..XXXXXXX 100644
34
int bytes);
43
--- a/include/block/block_int.h
35
int blk_truncate(BlockBackend *blk, int64_t offset, bool exact,
44
+++ b/include/block/block_int.h
36
- PreallocMode prealloc, Error **errp);
45
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
37
+ PreallocMode prealloc, BdrvRequestFlags flags, Error **errp);
46
int (*bdrv_file_open)(BlockDriverState *bs, QDict *options, int flags,
38
int blk_pdiscard(BlockBackend *blk, int64_t offset, int bytes);
47
Error **errp);
39
int blk_save_vmstate(BlockBackend *blk, const uint8_t *buf,
48
void (*bdrv_close)(BlockDriverState *bs);
40
int64_t pos, int size);
49
- int (*bdrv_create)(const char *filename, QemuOpts *opts, Error **errp);
50
+ int coroutine_fn (*bdrv_co_create_opts)(const char *filename, QemuOpts *opts,
51
+ Error **errp);
52
int (*bdrv_make_empty)(BlockDriverState *bs);
53
54
void (*bdrv_refresh_filename)(BlockDriverState *bs, QDict *options);
55
diff --git a/block.c b/block.c
41
diff --git a/block.c b/block.c
56
index XXXXXXX..XXXXXXX 100644
42
index XXXXXXX..XXXXXXX 100644
57
--- a/block.c
43
--- a/block.c
58
+++ b/block.c
44
+++ b/block.c
59
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn bdrv_create_co_entry(void *opaque)
45
@@ -XXX,XX +XXX,XX @@ static int64_t create_file_fallback_truncate(BlockBackend *blk,
60
CreateCo *cco = opaque;
46
int64_t size;
61
assert(cco->drv);
47
int ret;
62
48
63
- ret = cco->drv->bdrv_create(cco->filename, cco->opts, &local_err);
49
- ret = blk_truncate(blk, minimum_size, false, PREALLOC_MODE_OFF, &local_err);
64
+ ret = cco->drv->bdrv_co_create_opts(cco->filename, cco->opts, &local_err);
50
+ ret = blk_truncate(blk, minimum_size, false, PREALLOC_MODE_OFF, 0,
65
error_propagate(&cco->err, local_err);
51
+ &local_err);
66
cco->ret = ret;
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,
67
}
60
}
68
@@ -XXX,XX +XXX,XX @@ int bdrv_create(BlockDriver *drv, const char* filename,
61
69
.err = NULL,
62
int blk_truncate(BlockBackend *blk, int64_t offset, bool exact,
70
};
63
- PreallocMode prealloc, Error **errp)
71
64
+ PreallocMode prealloc, BdrvRequestFlags flags, Error **errp)
72
- if (!drv->bdrv_create) {
65
{
73
+ if (!drv->bdrv_co_create_opts) {
66
if (!blk_is_available(blk)) {
74
error_setg(errp, "Driver '%s' does not support image creation", drv->format_name);
67
error_setg(errp, "No medium inserted");
75
ret = -ENOTSUP;
68
return -ENOMEDIUM;
76
goto out;
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);
77
diff --git a/block/crypto.c b/block/crypto.c
98
diff --git a/block/crypto.c b/block/crypto.c
78
index XXXXXXX..XXXXXXX 100644
99
index XXXXXXX..XXXXXXX 100644
79
--- a/block/crypto.c
100
--- a/block/crypto.c
80
+++ b/block/crypto.c
101
+++ b/block/crypto.c
81
@@ -XXX,XX +XXX,XX @@ static int block_crypto_open_luks(BlockDriverState *bs,
102
@@ -XXX,XX +XXX,XX @@ static ssize_t block_crypto_init_func(QCryptoBlock *block,
82
bs, options, flags, errp);
103
* which will be used by the crypto header
104
*/
105
return blk_truncate(data->blk, data->size + headerlen, false,
106
- data->prealloc, errp);
107
+ data->prealloc, 0, errp);
83
}
108
}
84
109
85
-static int block_crypto_create_luks(const char *filename,
110
86
- QemuOpts *opts,
111
diff --git a/block/mirror.c b/block/mirror.c
87
- Error **errp)
112
index XXXXXXX..XXXXXXX 100644
88
+static int coroutine_fn block_crypto_co_create_opts_luks(const char *filename,
113
--- a/block/mirror.c
89
+ QemuOpts *opts,
114
+++ b/block/mirror.c
90
+ Error **errp)
115
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn mirror_run(Job *job, Error **errp)
91
{
116
92
return block_crypto_create_generic(Q_CRYPTO_BLOCK_FORMAT_LUKS,
117
if (s->bdev_length > base_length) {
93
filename, opts, errp);
118
ret = blk_truncate(s->target, s->bdev_length, false,
94
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_crypto_luks = {
119
- PREALLOC_MODE_OFF, NULL);
95
.bdrv_open = block_crypto_open_luks,
120
+ PREALLOC_MODE_OFF, 0, NULL);
96
.bdrv_close = block_crypto_close,
121
if (ret < 0) {
97
.bdrv_child_perm = bdrv_format_default_perms,
122
goto immediate_exit;
98
- .bdrv_create = block_crypto_create_luks,
123
}
99
+ .bdrv_co_create_opts = block_crypto_co_create_opts_luks,
100
.bdrv_truncate = block_crypto_truncate,
101
.create_opts = &block_crypto_create_opts_luks,
102
103
diff --git a/block/file-posix.c b/block/file-posix.c
104
index XXXXXXX..XXXXXXX 100644
105
--- a/block/file-posix.c
106
+++ b/block/file-posix.c
107
@@ -XXX,XX +XXX,XX @@ static int64_t raw_get_allocated_file_size(BlockDriverState *bs)
108
return (int64_t)st.st_blocks * 512;
109
}
110
111
-static int raw_create(const char *filename, QemuOpts *opts, Error **errp)
112
+static int coroutine_fn raw_co_create_opts(const char *filename, QemuOpts *opts,
113
+ Error **errp)
114
{
115
int fd;
116
int result = 0;
117
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_file = {
118
.bdrv_reopen_commit = raw_reopen_commit,
119
.bdrv_reopen_abort = raw_reopen_abort,
120
.bdrv_close = raw_close,
121
- .bdrv_create = raw_create,
122
+ .bdrv_co_create_opts = raw_co_create_opts,
123
.bdrv_has_zero_init = bdrv_has_zero_init_1,
124
.bdrv_co_block_status = raw_co_block_status,
125
.bdrv_co_pwrite_zeroes = raw_co_pwrite_zeroes,
126
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int hdev_co_pwrite_zeroes(BlockDriverState *bs,
127
return -ENOTSUP;
128
}
129
130
-static int hdev_create(const char *filename, QemuOpts *opts,
131
- Error **errp)
132
+static int coroutine_fn hdev_co_create_opts(const char *filename, QemuOpts *opts,
133
+ Error **errp)
134
{
135
int fd;
136
int ret = 0;
137
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_host_device = {
138
.bdrv_reopen_prepare = raw_reopen_prepare,
139
.bdrv_reopen_commit = raw_reopen_commit,
140
.bdrv_reopen_abort = raw_reopen_abort,
141
- .bdrv_create = hdev_create,
142
+ .bdrv_co_create_opts = hdev_co_create_opts,
143
.create_opts = &raw_create_opts,
144
.bdrv_co_pwrite_zeroes = hdev_co_pwrite_zeroes,
145
146
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_host_cdrom = {
147
.bdrv_reopen_prepare = raw_reopen_prepare,
148
.bdrv_reopen_commit = raw_reopen_commit,
149
.bdrv_reopen_abort = raw_reopen_abort,
150
- .bdrv_create = hdev_create,
151
+ .bdrv_co_create_opts = hdev_co_create_opts,
152
.create_opts = &raw_create_opts,
153
154
155
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_host_cdrom = {
156
.bdrv_reopen_prepare = raw_reopen_prepare,
157
.bdrv_reopen_commit = raw_reopen_commit,
158
.bdrv_reopen_abort = raw_reopen_abort,
159
- .bdrv_create = hdev_create,
160
+ .bdrv_co_create_opts = hdev_co_create_opts,
161
.create_opts = &raw_create_opts,
162
163
.bdrv_co_preadv = raw_co_preadv,
164
diff --git a/block/file-win32.c b/block/file-win32.c
165
index XXXXXXX..XXXXXXX 100644
166
--- a/block/file-win32.c
167
+++ b/block/file-win32.c
168
@@ -XXX,XX +XXX,XX @@ static int64_t raw_get_allocated_file_size(BlockDriverState *bs)
169
return st.st_size;
170
}
171
172
-static int raw_create(const char *filename, QemuOpts *opts, Error **errp)
173
+static int coroutine_fn raw_co_create_opts(const char *filename, QemuOpts *opts,
174
+ Error **errp)
175
{
176
int fd;
177
int64_t total_size = 0;
178
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_file = {
179
.bdrv_file_open = raw_open,
180
.bdrv_refresh_limits = raw_probe_alignment,
181
.bdrv_close = raw_close,
182
- .bdrv_create = raw_create,
183
+ .bdrv_co_create_opts = raw_co_create_opts,
184
.bdrv_has_zero_init = bdrv_has_zero_init_1,
185
186
.bdrv_aio_readv = raw_aio_readv,
187
diff --git a/block/gluster.c b/block/gluster.c
188
index XXXXXXX..XXXXXXX 100644
189
--- a/block/gluster.c
190
+++ b/block/gluster.c
191
@@ -XXX,XX +XXX,XX @@ static int qemu_gluster_do_truncate(struct glfs_fd *fd, int64_t offset,
192
return 0;
193
}
194
195
-static int qemu_gluster_create(const char *filename,
196
- QemuOpts *opts, Error **errp)
197
+static int coroutine_fn qemu_gluster_co_create_opts(const char *filename,
198
+ QemuOpts *opts,
199
+ Error **errp)
200
{
201
BlockdevOptionsGluster *gconf;
202
struct glfs *glfs;
203
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_gluster = {
204
.bdrv_reopen_commit = qemu_gluster_reopen_commit,
205
.bdrv_reopen_abort = qemu_gluster_reopen_abort,
206
.bdrv_close = qemu_gluster_close,
207
- .bdrv_create = qemu_gluster_create,
208
+ .bdrv_co_create_opts = qemu_gluster_co_create_opts,
209
.bdrv_getlength = qemu_gluster_getlength,
210
.bdrv_get_allocated_file_size = qemu_gluster_allocated_file_size,
211
.bdrv_truncate = qemu_gluster_truncate,
212
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_gluster_tcp = {
213
.bdrv_reopen_commit = qemu_gluster_reopen_commit,
214
.bdrv_reopen_abort = qemu_gluster_reopen_abort,
215
.bdrv_close = qemu_gluster_close,
216
- .bdrv_create = qemu_gluster_create,
217
+ .bdrv_co_create_opts = qemu_gluster_co_create_opts,
218
.bdrv_getlength = qemu_gluster_getlength,
219
.bdrv_get_allocated_file_size = qemu_gluster_allocated_file_size,
220
.bdrv_truncate = qemu_gluster_truncate,
221
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_gluster_unix = {
222
.bdrv_reopen_commit = qemu_gluster_reopen_commit,
223
.bdrv_reopen_abort = qemu_gluster_reopen_abort,
224
.bdrv_close = qemu_gluster_close,
225
- .bdrv_create = qemu_gluster_create,
226
+ .bdrv_co_create_opts = qemu_gluster_co_create_opts,
227
.bdrv_getlength = qemu_gluster_getlength,
228
.bdrv_get_allocated_file_size = qemu_gluster_allocated_file_size,
229
.bdrv_truncate = qemu_gluster_truncate,
230
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_gluster_rdma = {
231
.bdrv_reopen_commit = qemu_gluster_reopen_commit,
232
.bdrv_reopen_abort = qemu_gluster_reopen_abort,
233
.bdrv_close = qemu_gluster_close,
234
- .bdrv_create = qemu_gluster_create,
235
+ .bdrv_co_create_opts = qemu_gluster_co_create_opts,
236
.bdrv_getlength = qemu_gluster_getlength,
237
.bdrv_get_allocated_file_size = qemu_gluster_allocated_file_size,
238
.bdrv_truncate = qemu_gluster_truncate,
239
diff --git a/block/iscsi.c b/block/iscsi.c
240
index XXXXXXX..XXXXXXX 100644
241
--- a/block/iscsi.c
242
+++ b/block/iscsi.c
243
@@ -XXX,XX +XXX,XX @@ static int iscsi_truncate(BlockDriverState *bs, int64_t offset,
244
return 0;
245
}
246
247
-static int iscsi_create(const char *filename, QemuOpts *opts, Error **errp)
248
+static int coroutine_fn iscsi_co_create_opts(const char *filename, QemuOpts *opts,
249
+ Error **errp)
250
{
251
int ret = 0;
252
int64_t total_size = 0;
253
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_iscsi = {
254
.bdrv_parse_filename = iscsi_parse_filename,
255
.bdrv_file_open = iscsi_open,
256
.bdrv_close = iscsi_close,
257
- .bdrv_create = iscsi_create,
258
+ .bdrv_co_create_opts = iscsi_co_create_opts,
259
.create_opts = &iscsi_create_opts,
260
.bdrv_reopen_prepare = iscsi_reopen_prepare,
261
.bdrv_reopen_commit = iscsi_reopen_commit,
262
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_iser = {
263
.bdrv_parse_filename = iscsi_parse_filename,
264
.bdrv_file_open = iscsi_open,
265
.bdrv_close = iscsi_close,
266
- .bdrv_create = iscsi_create,
267
+ .bdrv_co_create_opts = iscsi_co_create_opts,
268
.create_opts = &iscsi_create_opts,
269
.bdrv_reopen_prepare = iscsi_reopen_prepare,
270
.bdrv_reopen_commit = iscsi_reopen_commit,
271
diff --git a/block/nfs.c b/block/nfs.c
272
index XXXXXXX..XXXXXXX 100644
273
--- a/block/nfs.c
274
+++ b/block/nfs.c
275
@@ -XXX,XX +XXX,XX @@ static QemuOptsList nfs_create_opts = {
276
}
277
};
278
279
-static int nfs_file_create(const char *url, QemuOpts *opts, Error **errp)
280
+static int coroutine_fn nfs_file_co_create_opts(const char *url, QemuOpts *opts,
281
+ Error **errp)
282
{
283
int64_t ret, total_size;
284
NFSClient *client = g_new0(NFSClient, 1);
285
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_nfs = {
286
287
.bdrv_file_open = nfs_file_open,
288
.bdrv_close = nfs_file_close,
289
- .bdrv_create = nfs_file_create,
290
+ .bdrv_co_create_opts = nfs_file_co_create_opts,
291
.bdrv_reopen_prepare = nfs_reopen_prepare,
292
293
.bdrv_co_preadv = nfs_co_preadv,
294
diff --git a/block/parallels.c b/block/parallels.c
295
index XXXXXXX..XXXXXXX 100644
296
--- a/block/parallels.c
297
+++ b/block/parallels.c
298
@@ -XXX,XX +XXX,XX @@ static int parallels_check(BlockDriverState *bs, BdrvCheckResult *res,
299
}
300
301
302
-static int parallels_create(const char *filename, QemuOpts *opts, Error **errp)
303
+static int coroutine_fn parallels_co_create_opts(const char *filename,
304
+ QemuOpts *opts,
305
+ Error **errp)
306
{
307
int64_t total_size, cl_size;
308
uint8_t tmp[BDRV_SECTOR_SIZE];
309
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_parallels = {
310
.bdrv_co_readv = parallels_co_readv,
311
.bdrv_co_writev = parallels_co_writev,
312
.supports_backing = true,
313
- .bdrv_create = parallels_create,
314
+ .bdrv_co_create_opts = parallels_co_create_opts,
315
.bdrv_check = parallels_check,
316
.create_opts = &parallels_create_opts,
317
};
318
diff --git a/block/qcow.c b/block/qcow.c
319
index XXXXXXX..XXXXXXX 100644
320
--- a/block/qcow.c
321
+++ b/block/qcow.c
322
@@ -XXX,XX +XXX,XX @@ static void qcow_close(BlockDriverState *bs)
323
error_free(s->migration_blocker);
324
}
325
326
-static int qcow_create(const char *filename, QemuOpts *opts, Error **errp)
327
+static int coroutine_fn qcow_co_create_opts(const char *filename, QemuOpts *opts,
328
+ Error **errp)
329
{
330
int header_size, backing_filename_len, l1_size, shift, i;
331
QCowHeader header;
332
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_qcow = {
333
.bdrv_close        = qcow_close,
334
.bdrv_child_perm = bdrv_format_default_perms,
335
.bdrv_reopen_prepare = qcow_reopen_prepare,
336
- .bdrv_create = qcow_create,
337
+ .bdrv_co_create_opts = qcow_co_create_opts,
338
.bdrv_has_zero_init = bdrv_has_zero_init_1,
339
.supports_backing = true,
340
341
diff --git a/block/qcow2.c b/block/qcow2.c
124
diff --git a/block/qcow2.c b/block/qcow2.c
342
index XXXXXXX..XXXXXXX 100644
125
index XXXXXXX..XXXXXXX 100644
343
--- a/block/qcow2.c
126
--- a/block/qcow2.c
344
+++ b/block/qcow2.c
127
+++ b/block/qcow2.c
345
@@ -XXX,XX +XXX,XX @@ out:
128
@@ -XXX,XX +XXX,XX @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp)
346
return ret;
129
347
}
130
/* Okay, now that we have a valid image, let's give it the right size */
348
131
ret = blk_truncate(blk, qcow2_opts->size, false, qcow2_opts->preallocation,
349
-static int qcow2_create(const char *filename, QemuOpts *opts, Error **errp)
132
- errp);
350
+static int coroutine_fn qcow2_co_create_opts(const char *filename, QemuOpts *opts,
133
+ 0, errp);
351
+ Error **errp)
134
if (ret < 0) {
352
{
135
error_prepend(errp, "Could not resize image: ");
353
char *backing_file = NULL;
136
goto out;
354
char *backing_fmt = NULL;
137
@@ -XXX,XX +XXX,XX @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts,
355
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_qcow2 = {
138
* Amending image options should ensure that the image has
356
.bdrv_reopen_abort = qcow2_reopen_abort,
139
* exactly the given new values, so pass exact=true here.
357
.bdrv_join_options = qcow2_join_options,
140
*/
358
.bdrv_child_perm = bdrv_format_default_perms,
141
- ret = blk_truncate(blk, new_size, true, PREALLOC_MODE_OFF, errp);
359
- .bdrv_create = qcow2_create,
142
+ ret = blk_truncate(blk, new_size, true, PREALLOC_MODE_OFF, 0, errp);
360
+ .bdrv_co_create_opts = qcow2_co_create_opts,
143
blk_unref(blk);
361
.bdrv_has_zero_init = bdrv_has_zero_init_1,
144
if (ret < 0) {
362
.bdrv_co_block_status = qcow2_co_block_status,
145
return ret;
363
364
diff --git a/block/qed.c b/block/qed.c
146
diff --git a/block/qed.c b/block/qed.c
365
index XXXXXXX..XXXXXXX 100644
147
index XXXXXXX..XXXXXXX 100644
366
--- a/block/qed.c
148
--- a/block/qed.c
367
+++ b/block/qed.c
149
+++ b/block/qed.c
368
@@ -XXX,XX +XXX,XX @@ out:
150
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_qed_co_create(BlockdevCreateOptions *opts,
369
return ret;
151
* The QED format associates file length with allocation status,
370
}
152
* so a new file (which is empty) must have a length of 0.
371
153
*/
372
-static int bdrv_qed_create(const char *filename, QemuOpts *opts, Error **errp)
154
- ret = blk_truncate(blk, 0, true, PREALLOC_MODE_OFF, errp);
373
+static int coroutine_fn bdrv_qed_co_create_opts(const char *filename,
155
+ ret = blk_truncate(blk, 0, true, PREALLOC_MODE_OFF, 0, errp);
374
+ QemuOpts *opts,
156
if (ret < 0) {
375
+ Error **errp)
157
goto out;
376
{
158
}
377
uint64_t image_size = 0;
378
uint32_t cluster_size = QED_DEFAULT_CLUSTER_SIZE;
379
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_qed = {
380
.bdrv_close = bdrv_qed_close,
381
.bdrv_reopen_prepare = bdrv_qed_reopen_prepare,
382
.bdrv_child_perm = bdrv_format_default_perms,
383
- .bdrv_create = bdrv_qed_create,
384
+ .bdrv_co_create_opts = bdrv_qed_co_create_opts,
385
.bdrv_has_zero_init = bdrv_has_zero_init_1,
386
.bdrv_co_block_status = bdrv_qed_co_block_status,
387
.bdrv_co_readv = bdrv_qed_co_readv,
388
diff --git a/block/raw-format.c b/block/raw-format.c
389
index XXXXXXX..XXXXXXX 100644
390
--- a/block/raw-format.c
391
+++ b/block/raw-format.c
392
@@ -XXX,XX +XXX,XX @@ static int raw_has_zero_init(BlockDriverState *bs)
393
return bdrv_has_zero_init(bs->file->bs);
394
}
395
396
-static int raw_create(const char *filename, QemuOpts *opts, Error **errp)
397
+static int coroutine_fn raw_co_create_opts(const char *filename, QemuOpts *opts,
398
+ Error **errp)
399
{
400
return bdrv_create_file(filename, opts, errp);
401
}
402
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_raw = {
403
.bdrv_open = &raw_open,
404
.bdrv_close = &raw_close,
405
.bdrv_child_perm = bdrv_filter_default_perms,
406
- .bdrv_create = &raw_create,
407
+ .bdrv_co_create_opts = &raw_co_create_opts,
408
.bdrv_co_preadv = &raw_co_preadv,
409
.bdrv_co_pwritev = &raw_co_pwritev,
410
.bdrv_co_pwrite_zeroes = &raw_co_pwrite_zeroes,
411
diff --git a/block/rbd.c b/block/rbd.c
412
index XXXXXXX..XXXXXXX 100644
413
--- a/block/rbd.c
414
+++ b/block/rbd.c
415
@@ -XXX,XX +XXX,XX @@ static QemuOptsList runtime_opts = {
416
},
417
};
418
419
-static int qemu_rbd_create(const char *filename, QemuOpts *opts, Error **errp)
420
+static int coroutine_fn qemu_rbd_co_create_opts(const char *filename,
421
+ QemuOpts *opts,
422
+ Error **errp)
423
{
424
Error *local_err = NULL;
425
int64_t bytes = 0;
426
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_rbd = {
427
.bdrv_file_open = qemu_rbd_open,
428
.bdrv_close = qemu_rbd_close,
429
.bdrv_reopen_prepare = qemu_rbd_reopen_prepare,
430
- .bdrv_create = qemu_rbd_create,
431
+ .bdrv_co_create_opts = qemu_rbd_co_create_opts,
432
.bdrv_has_zero_init = bdrv_has_zero_init_1,
433
.bdrv_get_info = qemu_rbd_getinfo,
434
.create_opts = &qemu_rbd_create_opts,
435
diff --git a/block/sheepdog.c b/block/sheepdog.c
436
index XXXXXXX..XXXXXXX 100644
437
--- a/block/sheepdog.c
438
+++ b/block/sheepdog.c
439
@@ -XXX,XX +XXX,XX @@ static int parse_block_size_shift(BDRVSheepdogState *s, QemuOpts *opt)
440
return 0;
441
}
442
443
-static int sd_create(const char *filename, QemuOpts *opts,
444
- Error **errp)
445
+static int coroutine_fn sd_co_create_opts(const char *filename, QemuOpts *opts,
446
+ Error **errp)
447
{
448
Error *err = NULL;
449
int ret = 0;
450
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_sheepdog = {
451
.bdrv_reopen_commit = sd_reopen_commit,
452
.bdrv_reopen_abort = sd_reopen_abort,
453
.bdrv_close = sd_close,
454
- .bdrv_create = sd_create,
455
+ .bdrv_co_create_opts = sd_co_create_opts,
456
.bdrv_has_zero_init = bdrv_has_zero_init_1,
457
.bdrv_getlength = sd_getlength,
458
.bdrv_get_allocated_file_size = sd_get_allocated_file_size,
459
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_sheepdog_tcp = {
460
.bdrv_reopen_commit = sd_reopen_commit,
461
.bdrv_reopen_abort = sd_reopen_abort,
462
.bdrv_close = sd_close,
463
- .bdrv_create = sd_create,
464
+ .bdrv_co_create_opts = sd_co_create_opts,
465
.bdrv_has_zero_init = bdrv_has_zero_init_1,
466
.bdrv_getlength = sd_getlength,
467
.bdrv_get_allocated_file_size = sd_get_allocated_file_size,
468
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_sheepdog_unix = {
469
.bdrv_reopen_commit = sd_reopen_commit,
470
.bdrv_reopen_abort = sd_reopen_abort,
471
.bdrv_close = sd_close,
472
- .bdrv_create = sd_create,
473
+ .bdrv_co_create_opts = sd_co_create_opts,
474
.bdrv_has_zero_init = bdrv_has_zero_init_1,
475
.bdrv_getlength = sd_getlength,
476
.bdrv_get_allocated_file_size = sd_get_allocated_file_size,
477
diff --git a/block/ssh.c b/block/ssh.c
478
index XXXXXXX..XXXXXXX 100644
479
--- a/block/ssh.c
480
+++ b/block/ssh.c
481
@@ -XXX,XX +XXX,XX @@ static QemuOptsList ssh_create_opts = {
482
}
483
};
484
485
-static int ssh_create(const char *filename, QemuOpts *opts, Error **errp)
486
+static int coroutine_fn ssh_co_create_opts(const char *filename, QemuOpts *opts,
487
+ Error **errp)
488
{
489
int r, ret;
490
int64_t total_size = 0;
491
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_ssh = {
492
.instance_size = sizeof(BDRVSSHState),
493
.bdrv_parse_filename = ssh_parse_filename,
494
.bdrv_file_open = ssh_file_open,
495
- .bdrv_create = ssh_create,
496
+ .bdrv_co_create_opts = ssh_co_create_opts,
497
.bdrv_close = ssh_close,
498
.bdrv_has_zero_init = ssh_has_zero_init,
499
.bdrv_co_readv = ssh_co_readv,
500
diff --git a/block/vdi.c b/block/vdi.c
159
diff --git a/block/vdi.c b/block/vdi.c
501
index XXXXXXX..XXXXXXX 100644
160
index XXXXXXX..XXXXXXX 100644
502
--- a/block/vdi.c
161
--- a/block/vdi.c
503
+++ b/block/vdi.c
162
+++ b/block/vdi.c
504
@@ -XXX,XX +XXX,XX @@ nonallocating_write:
163
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vdi_co_do_create(BlockdevCreateOptions *create_options,
505
return ret;
164
506
}
165
if (image_type == VDI_TYPE_STATIC) {
507
166
ret = blk_truncate(blk, offset + blocks * block_size, false,
508
-static int vdi_create(const char *filename, QemuOpts *opts, Error **errp)
167
- PREALLOC_MODE_OFF, errp);
509
+static int coroutine_fn vdi_co_create_opts(const char *filename, QemuOpts *opts,
168
+ PREALLOC_MODE_OFF, 0, errp);
510
+ Error **errp)
169
if (ret < 0) {
511
{
170
error_prepend(errp, "Failed to statically allocate file");
512
int ret = 0;
171
goto exit;
513
uint64_t bytes = 0;
514
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_vdi = {
515
.bdrv_close = vdi_close,
516
.bdrv_reopen_prepare = vdi_reopen_prepare,
517
.bdrv_child_perm = bdrv_format_default_perms,
518
- .bdrv_create = vdi_create,
519
+ .bdrv_co_create_opts = vdi_co_create_opts,
520
.bdrv_has_zero_init = bdrv_has_zero_init_1,
521
.bdrv_co_block_status = vdi_co_block_status,
522
.bdrv_make_empty = vdi_make_empty,
523
diff --git a/block/vhdx.c b/block/vhdx.c
172
diff --git a/block/vhdx.c b/block/vhdx.c
524
index XXXXXXX..XXXXXXX 100644
173
index XXXXXXX..XXXXXXX 100644
525
--- a/block/vhdx.c
174
--- a/block/vhdx.c
526
+++ b/block/vhdx.c
175
+++ b/block/vhdx.c
527
@@ -XXX,XX +XXX,XX @@ exit:
176
@@ -XXX,XX +XXX,XX @@ static int vhdx_create_bat(BlockBackend *blk, BDRVVHDXState *s,
528
* .---- ~ ----------- ~ ------------ ~ ---------------- ~ -----------.
177
/* All zeroes, so we can just extend the file - the end of the BAT
529
* 1MB
178
* is the furthest thing we have written yet */
530
*/
179
ret = blk_truncate(blk, data_file_offset, false, PREALLOC_MODE_OFF,
531
-static int vhdx_create(const char *filename, QemuOpts *opts, Error **errp)
180
- errp);
532
+static int coroutine_fn vhdx_co_create_opts(const char *filename, QemuOpts *opts,
181
+ 0, errp);
533
+ Error **errp)
182
if (ret < 0) {
534
{
183
goto exit;
535
int ret = 0;
184
}
536
uint64_t image_size = (uint64_t) 2 * GiB;
185
} else if (type == VHDX_TYPE_FIXED) {
537
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_vhdx = {
186
ret = blk_truncate(blk, data_file_offset + image_size, false,
538
.bdrv_child_perm = bdrv_format_default_perms,
187
- PREALLOC_MODE_OFF, errp);
539
.bdrv_co_readv = vhdx_co_readv,
188
+ PREALLOC_MODE_OFF, 0, errp);
540
.bdrv_co_writev = vhdx_co_writev,
189
if (ret < 0) {
541
- .bdrv_create = vhdx_create,
190
goto exit;
542
+ .bdrv_co_create_opts = vhdx_co_create_opts,
191
}
543
.bdrv_get_info = vhdx_get_info,
544
.bdrv_check = vhdx_check,
545
.bdrv_has_zero_init = bdrv_has_zero_init_1,
546
diff --git a/block/vmdk.c b/block/vmdk.c
192
diff --git a/block/vmdk.c b/block/vmdk.c
547
index XXXXXXX..XXXXXXX 100644
193
index XXXXXXX..XXXXXXX 100644
548
--- a/block/vmdk.c
194
--- a/block/vmdk.c
549
+++ b/block/vmdk.c
195
+++ b/block/vmdk.c
550
@@ -XXX,XX +XXX,XX @@ static int filename_decompose(const char *filename, char *path, char *prefix,
196
@@ -XXX,XX +XXX,XX @@ static int vmdk_init_extent(BlockBackend *blk,
551
return VMDK_OK;
197
int gd_buf_size;
552
}
198
553
199
if (flat) {
554
-static int vmdk_create(const char *filename, QemuOpts *opts, Error **errp)
200
- ret = blk_truncate(blk, filesize, false, PREALLOC_MODE_OFF, errp);
555
+static int coroutine_fn vmdk_co_create_opts(const char *filename, QemuOpts *opts,
201
+ ret = blk_truncate(blk, filesize, false, PREALLOC_MODE_OFF, 0, errp);
556
+ Error **errp)
202
goto exit;
557
{
203
}
558
int idx = 0;
204
magic = cpu_to_be32(VMDK4_MAGIC);
559
BlockBackend *new_blk = NULL;
205
@@ -XXX,XX +XXX,XX @@ static int vmdk_init_extent(BlockBackend *blk,
560
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_vmdk = {
206
}
561
.bdrv_co_pwritev_compressed = vmdk_co_pwritev_compressed,
207
562
.bdrv_co_pwrite_zeroes = vmdk_co_pwrite_zeroes,
208
ret = blk_truncate(blk, le64_to_cpu(header.grain_offset) << 9, false,
563
.bdrv_close = vmdk_close,
209
- PREALLOC_MODE_OFF, errp);
564
- .bdrv_create = vmdk_create,
210
+ PREALLOC_MODE_OFF, 0, errp);
565
+ .bdrv_co_create_opts = vmdk_co_create_opts,
211
if (ret < 0) {
566
.bdrv_co_flush_to_disk = vmdk_co_flush,
212
goto exit;
567
.bdrv_co_block_status = vmdk_co_block_status,
213
}
568
.bdrv_get_allocated_file_size = vmdk_get_allocated_file_size,
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
}
569
diff --git a/block/vpc.c b/block/vpc.c
223
diff --git a/block/vpc.c b/block/vpc.c
570
index XXXXXXX..XXXXXXX 100644
224
index XXXXXXX..XXXXXXX 100644
571
--- a/block/vpc.c
225
--- a/block/vpc.c
572
+++ b/block/vpc.c
226
+++ b/block/vpc.c
573
@@ -XXX,XX +XXX,XX @@ static int create_fixed_disk(BlockBackend *blk, uint8_t *buf,
227
@@ -XXX,XX +XXX,XX @@ static int create_fixed_disk(BlockBackend *blk, uint8_t *buf,
574
return ret;
228
/* Add footer to total size */
575
}
229
total_size += HEADER_SIZE;
576
230
577
-static int vpc_create(const char *filename, QemuOpts *opts, Error **errp)
231
- ret = blk_truncate(blk, total_size, false, PREALLOC_MODE_OFF, errp);
578
+static int coroutine_fn vpc_co_create_opts(const char *filename, QemuOpts *opts,
232
+ ret = blk_truncate(blk, total_size, false, PREALLOC_MODE_OFF, 0, errp);
579
+ Error **errp)
233
if (ret < 0) {
580
{
234
return ret;
581
uint8_t buf[1024];
235
}
582
VHDFooter *footer = (VHDFooter *) buf;
236
diff --git a/blockdev.c b/blockdev.c
583
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_vpc = {
237
index XXXXXXX..XXXXXXX 100644
584
.bdrv_close = vpc_close,
238
--- a/blockdev.c
585
.bdrv_reopen_prepare = vpc_reopen_prepare,
239
+++ b/blockdev.c
586
.bdrv_child_perm = bdrv_format_default_perms,
240
@@ -XXX,XX +XXX,XX @@ void qmp_block_resize(bool has_device, const char *device,
587
- .bdrv_create = vpc_create,
241
}
588
+ .bdrv_co_create_opts = vpc_co_create_opts,
242
589
243
bdrv_drained_begin(bs);
590
.bdrv_co_preadv = vpc_co_preadv,
244
- ret = blk_truncate(blk, size, false, PREALLOC_MODE_OFF, errp);
591
.bdrv_co_pwritev = vpc_co_pwritev,
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;
592
--
275
--
593
2.13.6
276
2.25.3
594
277
595
278
diff view generated by jsdifflib
1
From: Alberto Garcia <berto@igalia.com>
1
If BDRV_REQ_ZERO_WRITE is set and we're extending the image, calling
2
qcow2_cluster_zeroize() with flags=0 does the right thing: It doesn't
3
undo any previous preallocation, but just adds the zero flag to all
4
relevant L2 entries. If an external data file is in use, a write_zeroes
5
request to the data file is made instead.
2
6
3
The align_offset() function is equivalent to the ROUND_UP() macro so
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
there's no need to use the former. The ROUND_UP() name is also a bit
8
Message-Id: <20200424125448.63318-5-kwolf@redhat.com>
5
more explicit.
9
Reviewed-by: Eric Blake <eblake@redhat.com>
10
Reviewed-by: Max Reitz <mreitz@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
---
13
block/qcow2-cluster.c | 2 +-
14
block/qcow2.c | 34 ++++++++++++++++++++++++++++++++++
15
2 files changed, 35 insertions(+), 1 deletion(-)
6
16
7
This patch uses ROUND_UP() instead of the slower QEMU_ALIGN_UP()
8
because align_offset() already requires that the second parameter is a
9
power of two.
10
11
Signed-off-by: Alberto Garcia <berto@igalia.com>
12
Reviewed-by: Eric Blake <eblake@redhat.com>
13
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
14
Message-id: 20180215131008.5153-1-berto@igalia.com
15
Signed-off-by: Max Reitz <mreitz@redhat.com>
16
---
17
block/qcow2.h | 6 ------
18
block/qcow2-bitmap.c | 4 ++--
19
block/qcow2-cluster.c | 4 ++--
20
block/qcow2-refcount.c | 4 ++--
21
block/qcow2-snapshot.c | 10 +++++-----
22
block/qcow2.c | 14 +++++++-------
23
6 files changed, 18 insertions(+), 24 deletions(-)
24
25
diff --git a/block/qcow2.h b/block/qcow2.h
26
index XXXXXXX..XXXXXXX 100644
27
--- a/block/qcow2.h
28
+++ b/block/qcow2.h
29
@@ -XXX,XX +XXX,XX @@ static inline int offset_to_l2_slice_index(BDRVQcow2State *s, int64_t offset)
30
return (offset >> s->cluster_bits) & (s->l2_slice_size - 1);
31
}
32
33
-static inline int64_t align_offset(int64_t offset, int n)
34
-{
35
- offset = (offset + n - 1) & ~(n - 1);
36
- return offset;
37
-}
38
-
39
static inline int64_t qcow2_vm_state_offset(BDRVQcow2State *s)
40
{
41
return (int64_t)s->l1_vm_state_index << (s->cluster_bits + s->l2_bits);
42
diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c
43
index XXXXXXX..XXXXXXX 100644
44
--- a/block/qcow2-bitmap.c
45
+++ b/block/qcow2-bitmap.c
46
@@ -XXX,XX +XXX,XX @@ static inline void bitmap_dir_entry_to_be(Qcow2BitmapDirEntry *entry)
47
48
static inline int calc_dir_entry_size(size_t name_size, size_t extra_data_size)
49
{
50
- return align_offset(sizeof(Qcow2BitmapDirEntry) +
51
- name_size + extra_data_size, 8);
52
+ int size = sizeof(Qcow2BitmapDirEntry) + name_size + extra_data_size;
53
+ return ROUND_UP(size, 8);
54
}
55
56
static inline int dir_entry_size(Qcow2BitmapDirEntry *entry)
57
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
58
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
59
--- a/block/qcow2-cluster.c
19
--- a/block/qcow2-cluster.c
60
+++ b/block/qcow2-cluster.c
20
+++ b/block/qcow2-cluster.c
61
@@ -XXX,XX +XXX,XX @@ int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size,
21
@@ -XXX,XX +XXX,XX @@ int qcow2_cluster_zeroize(BlockDriverState *bs, uint64_t offset,
62
22
/* Caller must pass aligned values, except at image end */
63
new_l1_size2 = sizeof(uint64_t) * new_l1_size;
23
assert(QEMU_IS_ALIGNED(offset, s->cluster_size));
64
new_l1_table = qemu_try_blockalign(bs->file->bs,
24
assert(QEMU_IS_ALIGNED(end_offset, s->cluster_size) ||
65
- align_offset(new_l1_size2, 512));
25
- end_offset == bs->total_sectors << BDRV_SECTOR_BITS);
66
+ ROUND_UP(new_l1_size2, 512));
26
+ end_offset >= bs->total_sectors << BDRV_SECTOR_BITS);
67
if (new_l1_table == NULL) {
27
68
return -ENOMEM;
28
/* The zero flag is only supported by version 3 and newer */
69
}
29
if (s->qcow_version < 3) {
70
- memset(new_l1_table, 0, align_offset(new_l1_size2, 512));
71
+ memset(new_l1_table, 0, ROUND_UP(new_l1_size2, 512));
72
73
if (s->l1_size) {
74
memcpy(new_l1_table, s->l1_table, s->l1_size * sizeof(uint64_t));
75
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
76
index XXXXXXX..XXXXXXX 100644
77
--- a/block/qcow2-refcount.c
78
+++ b/block/qcow2-refcount.c
79
@@ -XXX,XX +XXX,XX @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
80
* l1_table_offset when it is the current s->l1_table_offset! Be careful
81
* when changing this! */
82
if (l1_table_offset != s->l1_table_offset) {
83
- l1_table = g_try_malloc0(align_offset(l1_size2, 512));
84
+ l1_table = g_try_malloc0(ROUND_UP(l1_size2, 512));
85
if (l1_size2 && l1_table == NULL) {
86
ret = -ENOMEM;
87
goto fail;
88
@@ -XXX,XX +XXX,XX @@ int qcow2_check_metadata_overlap(BlockDriverState *bs, int ign, int64_t offset,
89
}
90
91
/* align range to test to cluster boundaries */
92
- size = align_offset(offset_into_cluster(s, offset) + size, s->cluster_size);
93
+ size = ROUND_UP(offset_into_cluster(s, offset) + size, s->cluster_size);
94
offset = start_of_cluster(s, offset);
95
96
if ((chk & QCOW2_OL_ACTIVE_L1) && s->l1_size) {
97
diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c
98
index XXXXXXX..XXXXXXX 100644
99
--- a/block/qcow2-snapshot.c
100
+++ b/block/qcow2-snapshot.c
101
@@ -XXX,XX +XXX,XX @@ int qcow2_read_snapshots(BlockDriverState *bs)
102
103
for(i = 0; i < s->nb_snapshots; i++) {
104
/* Read statically sized part of the snapshot header */
105
- offset = align_offset(offset, 8);
106
+ offset = ROUND_UP(offset, 8);
107
ret = bdrv_pread(bs->file, offset, &h, sizeof(h));
108
if (ret < 0) {
109
goto fail;
110
@@ -XXX,XX +XXX,XX @@ static int qcow2_write_snapshots(BlockDriverState *bs)
111
offset = 0;
112
for(i = 0; i < s->nb_snapshots; i++) {
113
sn = s->snapshots + i;
114
- offset = align_offset(offset, 8);
115
+ offset = ROUND_UP(offset, 8);
116
offset += sizeof(h);
117
offset += sizeof(extra);
118
offset += strlen(sn->id_str);
119
@@ -XXX,XX +XXX,XX @@ static int qcow2_write_snapshots(BlockDriverState *bs)
120
assert(id_str_size <= UINT16_MAX && name_size <= UINT16_MAX);
121
h.id_str_size = cpu_to_be16(id_str_size);
122
h.name_size = cpu_to_be16(name_size);
123
- offset = align_offset(offset, 8);
124
+ offset = ROUND_UP(offset, 8);
125
126
ret = bdrv_pwrite(bs->file, offset, &h, sizeof(h));
127
if (ret < 0) {
128
@@ -XXX,XX +XXX,XX @@ int qcow2_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
129
/* The VM state isn't needed any more in the active L1 table; in fact, it
130
* hurts by causing expensive COW for the next snapshot. */
131
qcow2_cluster_discard(bs, qcow2_vm_state_offset(s),
132
- align_offset(sn->vm_state_size, s->cluster_size),
133
+ ROUND_UP(sn->vm_state_size, s->cluster_size),
134
QCOW2_DISCARD_NEVER, false);
135
136
#ifdef DEBUG_ALLOC
137
@@ -XXX,XX +XXX,XX @@ int qcow2_snapshot_load_tmp(BlockDriverState *bs,
138
}
139
new_l1_bytes = sn->l1_size * sizeof(uint64_t);
140
new_l1_table = qemu_try_blockalign(bs->file->bs,
141
- align_offset(new_l1_bytes, 512));
142
+ ROUND_UP(new_l1_bytes, 512));
143
if (new_l1_table == NULL) {
144
return -ENOMEM;
145
}
146
diff --git a/block/qcow2.c b/block/qcow2.c
30
diff --git a/block/qcow2.c b/block/qcow2.c
147
index XXXXXXX..XXXXXXX 100644
31
index XXXXXXX..XXXXXXX 100644
148
--- a/block/qcow2.c
32
--- a/block/qcow2.c
149
+++ b/block/qcow2.c
33
+++ b/block/qcow2.c
150
@@ -XXX,XX +XXX,XX @@ static int qcow2_do_open(BlockDriverState *bs, QDict *options, int flags,
34
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
151
35
152
if (s->l1_size > 0) {
36
bs->supported_zero_flags = header.version >= 3 ?
153
s->l1_table = qemu_try_blockalign(bs->file->bs,
37
BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK : 0;
154
- align_offset(s->l1_size * sizeof(uint64_t), 512));
38
+ bs->supported_truncate_flags = BDRV_REQ_ZERO_WRITE;
155
+ ROUND_UP(s->l1_size * sizeof(uint64_t), 512));
39
156
if (s->l1_table == NULL) {
40
/* Repair image if dirty */
157
error_setg(errp, "Could not allocate L1 table");
41
if (!(flags & (BDRV_O_CHECK | BDRV_O_INACTIVE)) && !bs->read_only &&
158
ret = -ENOMEM;
42
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
159
@@ -XXX,XX +XXX,XX @@ static int64_t qcow2_calc_prealloc_size(int64_t total_size,
43
g_assert_not_reached();
160
{
44
}
161
int64_t meta_size = 0;
45
162
uint64_t nl1e, nl2e;
46
+ if ((flags & BDRV_REQ_ZERO_WRITE) && offset > old_length) {
163
- int64_t aligned_total_size = align_offset(total_size, cluster_size);
47
+ uint64_t zero_start = QEMU_ALIGN_UP(old_length, s->cluster_size);
164
+ int64_t aligned_total_size = ROUND_UP(total_size, cluster_size);
48
+
165
49
+ /*
166
/* header: 1 cluster */
50
+ * Use zero clusters as much as we can. qcow2_cluster_zeroize()
167
meta_size += cluster_size;
51
+ * requires a cluster-aligned start. The end may be unaligned if it is
168
52
+ * at the end of the image (which it is here).
169
/* total size of L2 tables */
53
+ */
170
nl2e = aligned_total_size / cluster_size;
54
+ ret = qcow2_cluster_zeroize(bs, zero_start, offset - zero_start, 0);
171
- nl2e = align_offset(nl2e, cluster_size / sizeof(uint64_t));
55
+ if (ret < 0) {
172
+ nl2e = ROUND_UP(nl2e, cluster_size / sizeof(uint64_t));
56
+ error_setg_errno(errp, -ret, "Failed to zero out new clusters");
173
meta_size += nl2e * sizeof(uint64_t);
57
+ goto fail;
174
58
+ }
175
/* total size of L1 tables */
59
+
176
nl1e = nl2e * sizeof(uint64_t) / cluster_size;
60
+ /* Write explicit zeros for the unaligned head */
177
- nl1e = align_offset(nl1e, cluster_size / sizeof(uint64_t));
61
+ if (zero_start > old_length) {
178
+ nl1e = ROUND_UP(nl1e, cluster_size / sizeof(uint64_t));
62
+ uint64_t len = zero_start - old_length;
179
meta_size += nl1e * sizeof(uint64_t);
63
+ uint8_t *buf = qemu_blockalign0(bs, len);
180
64
+ QEMUIOVector qiov;
181
/* total size of refcount table and blocks */
65
+ qemu_iovec_init_buf(&qiov, buf, len);
182
@@ -XXX,XX +XXX,XX @@ static BlockMeasureInfo *qcow2_measure(QemuOpts *opts, BlockDriverState *in_bs,
66
+
183
has_backing_file = !!optstr;
67
+ qemu_co_mutex_unlock(&s->lock);
184
g_free(optstr);
68
+ ret = qcow2_co_pwritev_part(bs, old_length, len, &qiov, 0, 0);
185
69
+ qemu_co_mutex_lock(&s->lock);
186
- virtual_size = align_offset(qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0),
70
+
187
- cluster_size);
71
+ qemu_vfree(buf);
188
+ virtual_size = qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0);
72
+ if (ret < 0) {
189
+ virtual_size = ROUND_UP(virtual_size, cluster_size);
73
+ error_setg_errno(errp, -ret, "Failed to zero out the new area");
190
74
+ goto fail;
191
/* Check that virtual disk size is valid */
75
+ }
192
l2_tables = DIV_ROUND_UP(virtual_size / cluster_size,
76
+ }
193
@@ -XXX,XX +XXX,XX @@ static BlockMeasureInfo *qcow2_measure(QemuOpts *opts, BlockDriverState *in_bs,
77
+ }
194
goto err;
78
+
195
}
79
if (prealloc != PREALLOC_MODE_OFF) {
196
80
/* Flush metadata before actually changing the image size */
197
- virtual_size = align_offset(ssize, cluster_size);
81
ret = qcow2_write_caches(bs);
198
+ virtual_size = ROUND_UP(ssize, cluster_size);
199
200
if (has_backing_file) {
201
/* We don't how much of the backing chain is shared by the input
202
--
82
--
203
2.13.6
83
2.25.3
204
84
205
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. Update the raw driver accordingly.
5
Reviewed-by: Max Reitz <mreitz@redhat.com>
5
6
Reviewed-by: Eric Blake <eblake@redhat.com>
6
Signed-off-by: Eric Blake <eblake@redhat.com>
7
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
7
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
8
Reviewed-by: Fam Zheng <famz@redhat.com>
8
Message-Id: <20200424125448.63318-6-kwolf@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
10
---
11
block/raw-format.c | 16 ++++++++--------
11
block/raw-format.c | 4 +++-
12
1 file changed, 8 insertions(+), 8 deletions(-)
12
1 file changed, 3 insertions(+), 1 deletion(-)
13
13
14
diff --git a/block/raw-format.c b/block/raw-format.c
14
diff --git a/block/raw-format.c b/block/raw-format.c
15
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
16
--- a/block/raw-format.c
16
--- a/block/raw-format.c
17
+++ b/block/raw-format.c
17
+++ b/block/raw-format.c
18
@@ -XXX,XX +XXX,XX @@ fail:
18
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset,
19
return ret;
19
20
s->size = offset;
21
offset += s->offset;
22
- return bdrv_co_truncate(bs->file, offset, exact, prealloc, 0, errp);
23
+ return bdrv_co_truncate(bs->file, offset, exact, prealloc, flags, errp);
20
}
24
}
21
25
22
-static int64_t coroutine_fn raw_co_get_block_status(BlockDriverState *bs,
26
static void raw_eject(BlockDriverState *bs, bool eject_flag)
23
- int64_t sector_num,
27
@@ -XXX,XX +XXX,XX @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags,
24
- int nb_sectors, int *pnum,
28
bs->supported_zero_flags = BDRV_REQ_WRITE_UNCHANGED |
25
+static int coroutine_fn raw_co_block_status(BlockDriverState *bs,
29
((BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK) &
26
+ bool want_zero, int64_t offset,
30
bs->file->bs->supported_zero_flags);
27
+ int64_t bytes, int64_t *pnum,
31
+ bs->supported_truncate_flags = bs->file->bs->supported_truncate_flags &
28
+ int64_t *map,
32
+ BDRV_REQ_ZERO_WRITE;
29
BlockDriverState **file)
33
30
{
34
if (bs->probed && !bdrv_is_read_only(bs)) {
31
BDRVRawState *s = bs->opaque;
35
bdrv_refresh_filename(bs->file->bs);
32
- *pnum = nb_sectors;
33
+ *pnum = bytes;
34
*file = bs->file->bs;
35
- sector_num += s->offset / BDRV_SECTOR_SIZE;
36
- return BDRV_BLOCK_RAW | BDRV_BLOCK_OFFSET_VALID |
37
- (sector_num << BDRV_SECTOR_BITS);
38
+ *map = offset + s->offset;
39
+ return BDRV_BLOCK_RAW | BDRV_BLOCK_OFFSET_VALID;
40
}
41
42
static int coroutine_fn raw_co_pwrite_zeroes(BlockDriverState *bs,
43
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_raw = {
44
.bdrv_co_pwritev = &raw_co_pwritev,
45
.bdrv_co_pwrite_zeroes = &raw_co_pwrite_zeroes,
46
.bdrv_co_pdiscard = &raw_co_pdiscard,
47
- .bdrv_co_get_block_status = &raw_co_get_block_status,
48
+ .bdrv_co_block_status = &raw_co_block_status,
49
.bdrv_truncate = &raw_truncate,
50
.bdrv_getlength = &raw_getlength,
51
.has_variable_length = true,
52
--
36
--
53
2.13.6
37
2.25.3
54
38
55
39
diff view generated by jsdifflib
1
From: Eric Blake <eblake@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
We are gradually moving away from sector-based interfaces, towards
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
byte-based. Update the file protocol driver accordingly.
5
6
In want_zero mode, we continue to report fine-grained hole
7
information (the caller wants as much mapping detail as possible);
8
but when not in that mode, the caller prefers larger *pnum and
9
merely cares about what offsets are allocated at this layer, rather
10
than where the holes live. Since holes still read as zeroes at
11
this layer (rather than deferring to a backing layer), we can take
12
the shortcut of skipping lseek(), and merely state that all bytes
13
are allocated.
14
15
We can also drop redundant bounds checks that are already
16
guaranteed by the block layer.
17
18
Signed-off-by: Eric Blake <eblake@redhat.com>
19
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
5
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
20
Reviewed-by: Fam Zheng <famz@redhat.com>
6
Reviewed-by: Alberto Garcia <berto@igalia.com>
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
8
Message-Id: <20200424125448.63318-7-kwolf@redhat.com>
21
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
22
---
10
---
23
block/file-posix.c | 64 +++++++++++++++++++++++++-----------------------------
11
block/file-posix.c | 4 ++++
24
1 file changed, 30 insertions(+), 34 deletions(-)
12
1 file changed, 4 insertions(+)
25
13
26
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
27
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
28
--- a/block/file-posix.c
16
--- a/block/file-posix.c
29
+++ b/block/file-posix.c
17
+++ b/block/file-posix.c
30
@@ -XXX,XX +XXX,XX @@ static int find_allocation(BlockDriverState *bs, off_t start,
18
@@ -XXX,XX +XXX,XX @@ static int raw_open_common(BlockDriverState *bs, QDict *options,
31
}
19
#endif
32
20
33
/*
21
bs->supported_zero_flags = BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK;
34
- * Returns the allocation status of the specified sectors.
22
+ if (S_ISREG(st.st_mode)) {
35
+ * Returns the allocation status of the specified offset.
23
+ /* When extending regular files, we get zeros from the OS */
36
*
24
+ bs->supported_truncate_flags = BDRV_REQ_ZERO_WRITE;
37
- * If 'sector_num' is beyond the end of the disk image the return value is 0
25
+ }
38
- * and 'pnum' is set to 0.
26
ret = 0;
39
+ * The block layer guarantees 'offset' and 'bytes' are within bounds.
27
fail:
40
*
28
if (filename && (bdrv_flags & BDRV_O_TEMPORARY)) {
41
- * 'pnum' is set to the number of sectors (including and immediately following
42
- * the specified sector) that are known to be in the same
43
+ * 'pnum' is set to the number of bytes (including and immediately following
44
+ * the specified offset) that are known to be in the same
45
* allocated/unallocated state.
46
*
47
- * 'nb_sectors' is the max value 'pnum' should be set to. If nb_sectors goes
48
- * beyond the end of the disk image it will be clamped.
49
+ * 'bytes' is the max value 'pnum' should be set to.
50
*/
51
-static int64_t coroutine_fn raw_co_get_block_status(BlockDriverState *bs,
52
- int64_t sector_num,
53
- int nb_sectors, int *pnum,
54
- BlockDriverState **file)
55
-{
56
- off_t start, data = 0, hole = 0;
57
- int64_t total_size;
58
+static int coroutine_fn raw_co_block_status(BlockDriverState *bs,
59
+ bool want_zero,
60
+ int64_t offset,
61
+ int64_t bytes, int64_t *pnum,
62
+ int64_t *map,
63
+ BlockDriverState **file)
64
+{
65
+ off_t data = 0, hole = 0;
66
int ret;
67
68
ret = fd_open(bs);
69
@@ -XXX,XX +XXX,XX @@ static int64_t coroutine_fn raw_co_get_block_status(BlockDriverState *bs,
70
return ret;
71
}
72
73
- start = sector_num * BDRV_SECTOR_SIZE;
74
- total_size = bdrv_getlength(bs);
75
- if (total_size < 0) {
76
- return total_size;
77
- } else if (start >= total_size) {
78
- *pnum = 0;
79
- return 0;
80
- } else if (start + nb_sectors * BDRV_SECTOR_SIZE > total_size) {
81
- nb_sectors = DIV_ROUND_UP(total_size - start, BDRV_SECTOR_SIZE);
82
+ if (!want_zero) {
83
+ *pnum = bytes;
84
+ *map = offset;
85
+ *file = bs;
86
+ return BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID;
87
}
88
89
- ret = find_allocation(bs, start, &data, &hole);
90
+ ret = find_allocation(bs, offset, &data, &hole);
91
if (ret == -ENXIO) {
92
/* Trailing hole */
93
- *pnum = nb_sectors;
94
+ *pnum = bytes;
95
ret = BDRV_BLOCK_ZERO;
96
} else if (ret < 0) {
97
/* No info available, so pretend there are no holes */
98
- *pnum = nb_sectors;
99
+ *pnum = bytes;
100
ret = BDRV_BLOCK_DATA;
101
- } else if (data == start) {
102
- /* On a data extent, compute sectors to the end of the extent,
103
+ } else if (data == offset) {
104
+ /* On a data extent, compute bytes to the end of the extent,
105
* possibly including a partial sector at EOF. */
106
- *pnum = MIN(nb_sectors, DIV_ROUND_UP(hole - start, BDRV_SECTOR_SIZE));
107
+ *pnum = MIN(bytes, hole - offset);
108
ret = BDRV_BLOCK_DATA;
109
} else {
110
- /* On a hole, compute sectors to the beginning of the next extent. */
111
- assert(hole == start);
112
- *pnum = MIN(nb_sectors, (data - start) / BDRV_SECTOR_SIZE);
113
+ /* On a hole, compute bytes to the beginning of the next extent. */
114
+ assert(hole == offset);
115
+ *pnum = MIN(bytes, data - offset);
116
ret = BDRV_BLOCK_ZERO;
117
}
118
+ *map = offset;
119
*file = bs;
120
- return ret | BDRV_BLOCK_OFFSET_VALID | start;
121
+ return ret | BDRV_BLOCK_OFFSET_VALID;
122
}
123
124
static coroutine_fn BlockAIOCB *raw_aio_pdiscard(BlockDriverState *bs,
125
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_file = {
126
.bdrv_close = raw_close,
127
.bdrv_create = raw_create,
128
.bdrv_has_zero_init = bdrv_has_zero_init_1,
129
- .bdrv_co_get_block_status = raw_co_get_block_status,
130
+ .bdrv_co_block_status = raw_co_block_status,
131
.bdrv_co_pwrite_zeroes = raw_co_pwrite_zeroes,
132
133
.bdrv_co_preadv = raw_co_preadv,
134
--
29
--
135
2.13.6
30
2.25.3
136
31
137
32
diff view generated by jsdifflib
1
From: Anton Nefedov <anton.nefedov@virtuozzo.com>
1
When extending the size of an image that has a backing file larger than
2
its old size, make sure that the backing file data doesn't become
3
visible in the guest, but the added area is properly zeroed out.
2
4
3
The normal bdrv_co_pwritev() use is either
5
Consider the following scenario where the overlay is shorter than its
4
- BDRV_REQ_ZERO_WRITE clear and iovector provided
6
backing file:
5
- BDRV_REQ_ZERO_WRITE set and iovector == NULL
6
7
7
while
8
base.qcow2: AAAAAAAA
8
- the flag clear and iovector == NULL is an assertion failure
9
overlay.qcow2: BBBB
9
in bdrv_co_do_zero_pwritev()
10
- the flag set and iovector provided is in fact allowed
11
(the flag prevails and zeroes are written)
12
10
13
However the alignment logic does not support the latter case so the padding
11
When resizing (extending) overlay.qcow2, the new blocks should not stay
14
areas get overwritten with zeroes.
12
unallocated and make the additional As from base.qcow2 visible like
13
before this patch, but zeros should be read.
15
14
16
Currently, general functions like bdrv_rw_co() do provide iovector
15
A similar case happens with the various variants of a commit job when an
17
regardless of flags. So, keep it supported and use bdrv_co_do_zero_pwritev()
16
intermediate file is short (- for unallocated):
18
alignment for it which also makes the code a bit more obvious anyway.
19
17
20
Signed-off-by: Anton Nefedov <anton.nefedov@virtuozzo.com>
18
base.qcow2: A-A-AAAA
21
Reviewed-by: Eric Blake <eblake@redhat.com>
19
mid.qcow2: BB-B
22
Reviewed-by: Alberto Garcia <berto@igalia.com>
20
top.qcow2: C--C--C-
21
22
After commit top.qcow2 to mid.qcow2, the following happens:
23
24
mid.qcow2: CB-C00C0 (correct result)
25
mid.qcow2: CB-C--C- (before this fix)
26
27
Without the fix, blocks that previously read as zeros on top.qcow2
28
suddenly turn into A.
29
30
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
31
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
32
Message-Id: <20200424125448.63318-8-kwolf@redhat.com>
33
Reviewed-by: Max Reitz <mreitz@redhat.com>
23
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
34
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
24
---
35
---
25
block/io.c | 2 +-
36
block/io.c | 25 +++++++++++++++++++++++++
26
1 file changed, 1 insertion(+), 1 deletion(-)
37
1 file changed, 25 insertions(+)
27
38
28
diff --git a/block/io.c b/block/io.c
39
diff --git a/block/io.c b/block/io.c
29
index XXXXXXX..XXXXXXX 100644
40
index XXXXXXX..XXXXXXX 100644
30
--- a/block/io.c
41
--- a/block/io.c
31
+++ b/block/io.c
42
+++ b/block/io.c
32
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_pwritev(BdrvChild *child,
43
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
33
*/
34
tracked_request_begin(&req, bs, offset, bytes, BDRV_TRACKED_WRITE);
35
36
- if (!qiov) {
37
+ if (flags & BDRV_REQ_ZERO_WRITE) {
38
ret = bdrv_co_do_zero_pwritev(child, offset, bytes, flags, &req);
39
goto out;
44
goto out;
40
}
45
}
46
47
+ /*
48
+ * If the image has a backing file that is large enough that it would
49
+ * provide data for the new area, we cannot leave it unallocated because
50
+ * then the backing file content would become visible. Instead, zero-fill
51
+ * the new area.
52
+ *
53
+ * Note that if the image has a backing file, but was opened without the
54
+ * backing file, taking care of keeping things consistent with that backing
55
+ * file is the user's responsibility.
56
+ */
57
+ if (new_bytes && bs->backing) {
58
+ int64_t backing_len;
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
+ }
70
+ }
71
+
72
if (drv->bdrv_co_truncate) {
73
if (flags & ~bs->supported_truncate_flags) {
74
error_setg(errp, "Block driver does not support requested flags");
41
--
75
--
42
2.13.6
76
2.25.3
43
77
44
78
diff view generated by jsdifflib
1
This patch adds test cases for the scenario where blk_aio_flush() is
1
We want to keep TEST_IMG for the full path of the main test image, but
2
called on a BlockBackend with no root. Calling drain afterwards should
2
filter_testfiles() must be called for other test images before replacing
3
complete the requests with -ENOMEDIUM.
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
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
9
Reviewed-by: Max Reitz <mreitz@redhat.com>
7
Reviewed-by: Eric Blake <eblake@redhat.com>
10
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
11
Message-Id: <20200424125448.63318-9-kwolf@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
13
---
10
tests/test-block-backend.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++
14
tests/qemu-iotests/iotests.py | 5 +++--
11
tests/Makefile.include | 2 ++
15
1 file changed, 3 insertions(+), 2 deletions(-)
12
2 files changed, 84 insertions(+)
13
create mode 100644 tests/test-block-backend.c
14
16
15
diff --git a/tests/test-block-backend.c b/tests/test-block-backend.c
17
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
16
new file mode 100644
17
index XXXXXXX..XXXXXXX
18
--- /dev/null
19
+++ b/tests/test-block-backend.c
20
@@ -XXX,XX +XXX,XX @@
21
+/*
22
+ * BlockBackend tests
23
+ *
24
+ * Copyright (c) 2017 Kevin Wolf <kwolf@redhat.com>
25
+ *
26
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
27
+ * of this software and associated documentation files (the "Software"), to deal
28
+ * in the Software without restriction, including without limitation the rights
29
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
30
+ * copies of the Software, and to permit persons to whom the Software is
31
+ * furnished to do so, subject to the following conditions:
32
+ *
33
+ * The above copyright notice and this permission notice shall be included in
34
+ * all copies or substantial portions of the Software.
35
+ *
36
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
37
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
38
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
39
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
40
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
41
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
42
+ * THE SOFTWARE.
43
+ */
44
+
45
+#include "qemu/osdep.h"
46
+#include "block/block.h"
47
+#include "sysemu/block-backend.h"
48
+#include "qapi/error.h"
49
+
50
+static void test_drain_aio_error_flush_cb(void *opaque, int ret)
51
+{
52
+ bool *completed = opaque;
53
+
54
+ g_assert(ret == -ENOMEDIUM);
55
+ *completed = true;
56
+}
57
+
58
+static void test_drain_aio_error(void)
59
+{
60
+ BlockBackend *blk = blk_new(BLK_PERM_ALL, BLK_PERM_ALL);
61
+ BlockAIOCB *acb;
62
+ bool completed = false;
63
+
64
+ acb = blk_aio_flush(blk, test_drain_aio_error_flush_cb, &completed);
65
+ g_assert(acb != NULL);
66
+ g_assert(completed == false);
67
+
68
+ blk_drain(blk);
69
+ g_assert(completed == true);
70
+
71
+ blk_unref(blk);
72
+}
73
+
74
+static void test_drain_all_aio_error(void)
75
+{
76
+ BlockBackend *blk = blk_new(BLK_PERM_ALL, BLK_PERM_ALL);
77
+ BlockAIOCB *acb;
78
+ bool completed = false;
79
+
80
+ acb = blk_aio_flush(blk, test_drain_aio_error_flush_cb, &completed);
81
+ g_assert(acb != NULL);
82
+ g_assert(completed == false);
83
+
84
+ blk_drain_all();
85
+ g_assert(completed == true);
86
+
87
+ blk_unref(blk);
88
+}
89
+
90
+int main(int argc, char **argv)
91
+{
92
+ bdrv_init();
93
+ qemu_init_main_loop(&error_abort);
94
+
95
+ g_test_init(&argc, &argv, NULL);
96
+
97
+ g_test_add_func("/block-backend/drain_aio_error", test_drain_aio_error);
98
+ g_test_add_func("/block-backend/drain_all_aio_error",
99
+ test_drain_all_aio_error);
100
+
101
+ return g_test_run();
102
+}
103
diff --git a/tests/Makefile.include b/tests/Makefile.include
104
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
105
--- a/tests/Makefile.include
19
--- a/tests/qemu-iotests/iotests.py
106
+++ b/tests/Makefile.include
20
+++ b/tests/qemu-iotests/iotests.py
107
@@ -XXX,XX +XXX,XX @@ gcov-files-test-hbitmap-y = blockjob.c
21
@@ -XXX,XX +XXX,XX @@ def filter_img_info(output, filename):
108
check-unit-y += tests/test-bdrv-drain$(EXESUF)
22
for line in output.split('\n'):
109
check-unit-y += tests/test-blockjob$(EXESUF)
23
if 'disk size' in line or 'actual-size' in line:
110
check-unit-y += tests/test-blockjob-txn$(EXESUF)
24
continue
111
+check-unit-y += tests/test-block-backend$(EXESUF)
25
- line = line.replace(filename, 'TEST_IMG') \
112
check-unit-y += tests/test-x86-cpuid$(EXESUF)
26
- .replace(imgfmt, 'IMGFMT')
113
# all code tested by test-x86-cpuid is inside topology.h
27
+ line = line.replace(filename, 'TEST_IMG')
114
gcov-files-test-x86-cpuid-y =
28
+ line = filter_testfiles(line)
115
@@ -XXX,XX +XXX,XX @@ tests/test-throttle$(EXESUF): tests/test-throttle.o $(test-block-obj-y)
29
+ line = line.replace(imgfmt, 'IMGFMT')
116
tests/test-bdrv-drain$(EXESUF): tests/test-bdrv-drain.o $(test-block-obj-y) $(test-util-obj-y)
30
line = re.sub('iters: [0-9]+', 'iters: XXX', line)
117
tests/test-blockjob$(EXESUF): tests/test-blockjob.o $(test-block-obj-y) $(test-util-obj-y)
31
line = re.sub('uuid: [-a-f0-9]+', 'uuid: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX', line)
118
tests/test-blockjob-txn$(EXESUF): tests/test-blockjob-txn.o $(test-block-obj-y) $(test-util-obj-y)
32
line = re.sub('cid: [0-9]+', 'cid: XXXXXXXXXX', line)
119
+tests/test-block-backend$(EXESUF): tests/test-block-backend.o $(test-block-obj-y) $(test-util-obj-y)
120
tests/test-thread-pool$(EXESUF): tests/test-thread-pool.o $(test-block-obj-y)
121
tests/test-iov$(EXESUF): tests/test-iov.o $(test-util-obj-y)
122
tests/test-hbitmap$(EXESUF): tests/test-hbitmap.o $(test-util-obj-y) $(test-crypto-obj-y)
123
--
33
--
124
2.13.6
34
2.25.3
125
35
126
36
diff view generated by jsdifflib
1
From: Stefan Hajnoczi <stefanha@redhat.com>
1
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2
2
Message-Id: <20200424125448.63318-10-kwolf@redhat.com>
3
BlockDriverState has the BDRV_POLL_WHILE() macro to wait on event loop
3
Reviewed-by: Max Reitz <mreitz@redhat.com>
4
activity while a condition evaluates to true. This is used to implement
4
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
5
synchronous operations where it acts as a condvar between the IOThread
6
running the operation and the main loop waiting for the operation. It
7
can also be called from the thread that owns the AioContext and in that
8
case it's just a nested event loop.
9
10
BlockBackend needs this behavior but doesn't always have a
11
BlockDriverState it can use. This patch extracts BDRV_POLL_WHILE() into
12
the AioWait abstraction, which can be used with AioContext and isn't
13
tied to BlockDriverState anymore.
14
15
This feature could be built directly into AioContext but then all users
16
would kick the event loop even if they signal different conditions.
17
Imagine an AioContext with many BlockDriverStates, each time a request
18
completes any waiter would wake up and re-check their condition. It's
19
nicer to keep a separate AioWait object for each condition instead.
20
21
Please see "block/aio-wait.h" for details on the API.
22
23
The name AIO_WAIT_WHILE() avoids the confusion between AIO_POLL_WHILE()
24
and AioContext polling.
25
26
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
27
Reviewed-by: Eric Blake <eblake@redhat.com>
28
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
29
---
6
---
30
include/block/aio-wait.h | 116 ++++++++++++++++++++++++++++++++++++++++++++++
7
tests/qemu-iotests/274 | 155 +++++++++++++++++++++
31
include/block/block.h | 40 +++-------------
8
tests/qemu-iotests/274.out | 268 +++++++++++++++++++++++++++++++++++++
32
include/block/block_int.h | 7 ++-
9
tests/qemu-iotests/group | 1 +
33
block.c | 5 ++
10
3 files changed, 424 insertions(+)
34
block/io.c | 10 +---
11
create mode 100755 tests/qemu-iotests/274
35
util/aio-wait.c | 40 ++++++++++++++++
12
create mode 100644 tests/qemu-iotests/274.out
36
util/Makefile.objs | 2 +-
37
7 files changed, 174 insertions(+), 46 deletions(-)
38
create mode 100644 include/block/aio-wait.h
39
create mode 100644 util/aio-wait.c
40
13
41
diff --git a/include/block/aio-wait.h b/include/block/aio-wait.h
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
42
new file mode 100644
176
new file mode 100644
43
index XXXXXXX..XXXXXXX
177
index XXXXXXX..XXXXXXX
44
--- /dev/null
178
--- /dev/null
45
+++ b/include/block/aio-wait.h
179
+++ b/tests/qemu-iotests/274.out
46
@@ -XXX,XX +XXX,XX @@
180
@@ -XXX,XX +XXX,XX @@
47
+/*
181
+== Commit tests ==
48
+ * AioContext wait support
182
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=2097152 cluster_size=65536 lazy_refcounts=off refcount_bits=16
49
+ *
183
+
50
+ * Copyright (C) 2018 Red Hat, Inc.
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
51
+ *
185
+
52
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
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
53
+ * of this software and associated documentation files (the "Software"), to deal
187
+
54
+ * in the Software without restriction, including without limitation the rights
188
+wrote 2097152/2097152 bytes at offset 0
55
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
189
+2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
56
+ * copies of the Software, and to permit persons to whom the Software is
190
+
57
+ * furnished to do so, subject to the following conditions:
191
+=== Check visible data ===
58
+ *
192
+read 1048576/1048576 bytes at offset 0
59
+ * The above copyright notice and this permission notice shall be included in
193
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
60
+ * all copies or substantial portions of the Software.
194
+
61
+ *
195
+read 1048576/1048576 bytes at offset 1048576
62
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
196
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
63
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
197
+
64
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
198
+=== Checking allocation status ===
65
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
199
+1048576/1048576 bytes allocated at offset 0 bytes
66
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
200
+1048576/1048576 bytes allocated at offset 1 MiB
67
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
201
+
68
+ * THE SOFTWARE.
202
+0/1048576 bytes allocated at offset 0 bytes
69
+ */
203
+0/0 bytes allocated at offset 1 MiB
70
+
204
+
71
+#ifndef QEMU_AIO_WAIT_H
205
+0/1048576 bytes allocated at offset 0 bytes
72
+#define QEMU_AIO_WAIT_H
206
+0/1048576 bytes allocated at offset 1 MiB
73
+
207
+
74
+#include "block/aio.h"
208
+=== Checking map ===
75
+
209
+[{ "start": 0, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": 327680}]
76
+/**
210
+
77
+ * AioWait:
211
+Offset Length Mapped to File
78
+ *
212
+0 0x200000 0x50000 TEST_DIR/PID-base
79
+ * An object that facilitates synchronous waiting on a condition. The main
213
+
80
+ * loop can wait on an operation running in an IOThread as follows:
214
+[{ "start": 0, "length": 1048576, "depth": 1, "zero": false, "data": true, "offset": 327680}]
81
+ *
215
+
82
+ * AioWait *wait = ...;
216
+Offset Length Mapped to File
83
+ * AioContext *ctx = ...;
217
+0 0x100000 0x50000 TEST_DIR/PID-base
84
+ * MyWork work = { .done = false };
218
+
85
+ * schedule_my_work_in_iothread(ctx, &work);
219
+[{ "start": 0, "length": 1048576, "depth": 2, "zero": false, "data": true, "offset": 327680},
86
+ * AIO_WAIT_WHILE(wait, ctx, !work.done);
220
+{ "start": 1048576, "length": 1048576, "depth": 0, "zero": true, "data": false}]
87
+ *
221
+
88
+ * The IOThread must call aio_wait_kick() to notify the main loop when
222
+Offset Length Mapped to File
89
+ * work.done changes:
223
+0 0x100000 0x50000 TEST_DIR/PID-base
90
+ *
224
+
91
+ * static void do_work(...)
225
+=== Testing qemu-img commit (top -> mid) ===
92
+ * {
226
+Image committed.
93
+ * ...
227
+
94
+ * work.done = true;
228
+image: TEST_IMG
95
+ * aio_wait_kick(wait);
229
+file format: IMGFMT
96
+ * }
230
+virtual size: 2 MiB (2097152 bytes)
97
+ */
231
+cluster_size: 65536
98
+typedef struct {
232
+backing file: TEST_DIR/PID-base
99
+ /* Is the main loop waiting for a kick? Accessed with atomic ops. */
233
+Format specific information:
100
+ bool need_kick;
234
+ compat: 1.1
101
+} AioWait;
235
+ lazy refcounts: false
102
+
236
+ refcount bits: 16
103
+/**
237
+ corrupt: false
104
+ * AIO_WAIT_WHILE:
238
+
105
+ * @wait: the aio wait object
239
+read 1048576/1048576 bytes at offset 0
106
+ * @ctx: the aio context
240
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
107
+ * @cond: wait while this conditional expression is true
241
+
108
+ *
242
+read 1048576/1048576 bytes at offset 1048576
109
+ * Wait while a condition is true. Use this to implement synchronous
243
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
110
+ * operations that require event loop activity.
244
+
111
+ *
245
+=== Testing HMP commit (top -> mid) ===
112
+ * The caller must be sure that something calls aio_wait_kick() when the value
246
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=2097152 cluster_size=65536 lazy_refcounts=off refcount_bits=16
113
+ * of @cond might have changed.
247
+
114
+ *
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
115
+ * The caller's thread must be the IOThread that owns @ctx or the main loop
249
+
116
+ * thread (with @ctx acquired exactly once). This function cannot be used to
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
117
+ * wait on conditions between two IOThreads since that could lead to deadlock,
251
+
118
+ * go via the main loop instead.
252
+wrote 2097152/2097152 bytes at offset 0
119
+ */
253
+2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
120
+#define AIO_WAIT_WHILE(wait, ctx, cond) ({ \
254
+
121
+ bool waited_ = false; \
255
+{"execute": "human-monitor-command", "arguments": {"command-line": "commit drive0"}}
122
+ bool busy_ = true; \
256
+{"return": ""}
123
+ AioWait *wait_ = (wait); \
257
+image: TEST_IMG
124
+ AioContext *ctx_ = (ctx); \
258
+file format: IMGFMT
125
+ if (in_aio_context_home_thread(ctx_)) { \
259
+virtual size: 2 MiB (2097152 bytes)
126
+ while ((cond) || busy_) { \
260
+cluster_size: 65536
127
+ busy_ = aio_poll(ctx_, (cond)); \
261
+backing file: TEST_DIR/PID-base
128
+ waited_ |= !!(cond) | busy_; \
262
+Format specific information:
129
+ } \
263
+ compat: 1.1
130
+ } else { \
264
+ lazy refcounts: false
131
+ assert(qemu_get_current_aio_context() == \
265
+ refcount bits: 16
132
+ qemu_get_aio_context()); \
266
+ corrupt: false
133
+ assert(!wait_->need_kick); \
267
+
134
+ /* Set wait_->need_kick before evaluating cond. */ \
268
+read 1048576/1048576 bytes at offset 0
135
+ atomic_mb_set(&wait_->need_kick, true); \
269
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
136
+ while (busy_) { \
270
+
137
+ if ((cond)) { \
271
+read 1048576/1048576 bytes at offset 1048576
138
+ waited_ = busy_ = true; \
272
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
139
+ aio_context_release(ctx_); \
273
+
140
+ aio_poll(qemu_get_aio_context(), true); \
274
+=== Testing QMP active commit (top -> mid) ===
141
+ aio_context_acquire(ctx_); \
275
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=2097152 cluster_size=65536 lazy_refcounts=off refcount_bits=16
142
+ } else { \
276
+
143
+ busy_ = aio_poll(ctx_, false); \
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
144
+ waited_ |= busy_; \
278
+
145
+ } \
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
146
+ } \
280
+
147
+ atomic_set(&wait_->need_kick, false); \
281
+wrote 2097152/2097152 bytes at offset 0
148
+ } \
282
+2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
149
+ waited_; })
283
+
150
+
284
+{"execute": "block-commit", "arguments": {"auto-dismiss": false, "base-node": "mid", "device": "top", "job-id": "job0"}}
151
+/**
285
+{"return": {}}
152
+ * aio_wait_kick:
286
+{"execute": "job-complete", "arguments": {"id": "job0"}}
153
+ * @wait: the aio wait object that should re-evaluate its condition
287
+{"return": {}}
154
+ *
288
+{"data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "commit"}, "event": "BLOCK_JOB_READY", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
155
+ * Wake up the main thread if it is waiting on AIO_WAIT_WHILE(). During
289
+{"data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "commit"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
156
+ * synchronous operations performed in an IOThread, the main thread lets the
290
+{"execute": "job-dismiss", "arguments": {"id": "job0"}}
157
+ * IOThread's event loop run, waiting for the operation to complete. A
291
+{"return": {}}
158
+ * aio_wait_kick() call will wake up the main thread.
292
+image: TEST_IMG
159
+ */
293
+file format: IMGFMT
160
+void aio_wait_kick(AioWait *wait);
294
+virtual size: 2 MiB (2097152 bytes)
161
+
295
+cluster_size: 65536
162
+#endif /* QEMU_AIO_WAIT */
296
+backing file: TEST_DIR/PID-base
163
diff --git a/include/block/block.h b/include/block/block.h
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
164
index XXXXXXX..XXXXXXX 100644
450
index XXXXXXX..XXXXXXX 100644
165
--- a/include/block/block.h
451
--- a/tests/qemu-iotests/group
166
+++ b/include/block/block.h
452
+++ b/tests/qemu-iotests/group
167
@@ -XXX,XX +XXX,XX @@
453
@@ -XXX,XX +XXX,XX @@
168
#define BLOCK_H
454
270 rw backing quick
169
455
272 rw
170
#include "block/aio.h"
456
273 backing quick
171
+#include "block/aio-wait.h"
457
+274 rw backing
172
#include "qapi-types.h"
458
277 rw quick
173
#include "qemu/iov.h"
459
279 rw backing quick
174
#include "qemu/coroutine.h"
460
280 rw migration quick
175
@@ -XXX,XX +XXX,XX @@ void bdrv_drain_all_begin(void);
176
void bdrv_drain_all_end(void);
177
void bdrv_drain_all(void);
178
179
+/* Returns NULL when bs == NULL */
180
+AioWait *bdrv_get_aio_wait(BlockDriverState *bs);
181
+
182
#define BDRV_POLL_WHILE(bs, cond) ({ \
183
- bool waited_ = false; \
184
- bool busy_ = true; \
185
BlockDriverState *bs_ = (bs); \
186
- AioContext *ctx_ = bdrv_get_aio_context(bs_); \
187
- if (in_aio_context_home_thread(ctx_)) { \
188
- while ((cond) || busy_) { \
189
- busy_ = aio_poll(ctx_, (cond)); \
190
- waited_ |= !!(cond) | busy_; \
191
- } \
192
- } else { \
193
- assert(qemu_get_current_aio_context() == \
194
- qemu_get_aio_context()); \
195
- /* Ask bdrv_dec_in_flight to wake up the main \
196
- * QEMU AioContext. Extra I/O threads never take \
197
- * other I/O threads' AioContexts (see for example \
198
- * block_job_defer_to_main_loop for how to do it). \
199
- */ \
200
- assert(!bs_->wakeup); \
201
- /* Set bs->wakeup before evaluating cond. */ \
202
- atomic_mb_set(&bs_->wakeup, true); \
203
- while (busy_) { \
204
- if ((cond)) { \
205
- waited_ = busy_ = true; \
206
- aio_context_release(ctx_); \
207
- aio_poll(qemu_get_aio_context(), true); \
208
- aio_context_acquire(ctx_); \
209
- } else { \
210
- busy_ = aio_poll(ctx_, false); \
211
- waited_ |= busy_; \
212
- } \
213
- } \
214
- atomic_set(&bs_->wakeup, false); \
215
- } \
216
- waited_; })
217
+ AIO_WAIT_WHILE(bdrv_get_aio_wait(bs_), \
218
+ bdrv_get_aio_context(bs_), \
219
+ cond); })
220
221
int bdrv_pdiscard(BlockDriverState *bs, int64_t offset, int bytes);
222
int bdrv_co_pdiscard(BlockDriverState *bs, int64_t offset, int bytes);
223
diff --git a/include/block/block_int.h b/include/block/block_int.h
224
index XXXXXXX..XXXXXXX 100644
225
--- a/include/block/block_int.h
226
+++ b/include/block/block_int.h
227
@@ -XXX,XX +XXX,XX @@
228
229
#include "block/accounting.h"
230
#include "block/block.h"
231
+#include "block/aio-wait.h"
232
#include "qemu/queue.h"
233
#include "qemu/coroutine.h"
234
#include "qemu/stats64.h"
235
@@ -XXX,XX +XXX,XX @@ struct BlockDriverState {
236
unsigned int in_flight;
237
unsigned int serialising_in_flight;
238
239
- /* Internal to BDRV_POLL_WHILE and bdrv_wakeup. Accessed with atomic
240
- * ops.
241
- */
242
- bool wakeup;
243
+ /* Kicked to signal main loop when a request completes. */
244
+ AioWait wait;
245
246
/* counter for nested bdrv_io_plug.
247
* Accessed with atomic ops.
248
diff --git a/block.c b/block.c
249
index XXXXXXX..XXXXXXX 100644
250
--- a/block.c
251
+++ b/block.c
252
@@ -XXX,XX +XXX,XX @@ AioContext *bdrv_get_aio_context(BlockDriverState *bs)
253
return bs->aio_context;
254
}
255
256
+AioWait *bdrv_get_aio_wait(BlockDriverState *bs)
257
+{
258
+ return bs ? &bs->wait : NULL;
259
+}
260
+
261
void bdrv_coroutine_enter(BlockDriverState *bs, Coroutine *co)
262
{
263
aio_co_enter(bdrv_get_aio_context(bs), co);
264
diff --git a/block/io.c b/block/io.c
265
index XXXXXXX..XXXXXXX 100644
266
--- a/block/io.c
267
+++ b/block/io.c
268
@@ -XXX,XX +XXX,XX @@
269
#include "qemu/osdep.h"
270
#include "trace.h"
271
#include "sysemu/block-backend.h"
272
+#include "block/aio-wait.h"
273
#include "block/blockjob.h"
274
#include "block/blockjob_int.h"
275
#include "block/block_int.h"
276
@@ -XXX,XX +XXX,XX @@ void bdrv_inc_in_flight(BlockDriverState *bs)
277
atomic_inc(&bs->in_flight);
278
}
279
280
-static void dummy_bh_cb(void *opaque)
281
-{
282
-}
283
-
284
void bdrv_wakeup(BlockDriverState *bs)
285
{
286
- /* The barrier (or an atomic op) is in the caller. */
287
- if (atomic_read(&bs->wakeup)) {
288
- aio_bh_schedule_oneshot(qemu_get_aio_context(), dummy_bh_cb, NULL);
289
- }
290
+ aio_wait_kick(bdrv_get_aio_wait(bs));
291
}
292
293
void bdrv_dec_in_flight(BlockDriverState *bs)
294
diff --git a/util/aio-wait.c b/util/aio-wait.c
295
new file mode 100644
296
index XXXXXXX..XXXXXXX
297
--- /dev/null
298
+++ b/util/aio-wait.c
299
@@ -XXX,XX +XXX,XX @@
300
+/*
301
+ * AioContext wait support
302
+ *
303
+ * Copyright (C) 2018 Red Hat, Inc.
304
+ *
305
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
306
+ * of this software and associated documentation files (the "Software"), to deal
307
+ * in the Software without restriction, including without limitation the rights
308
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
309
+ * copies of the Software, and to permit persons to whom the Software is
310
+ * furnished to do so, subject to the following conditions:
311
+ *
312
+ * The above copyright notice and this permission notice shall be included in
313
+ * all copies or substantial portions of the Software.
314
+ *
315
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
316
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
317
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
318
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
319
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
320
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
321
+ * THE SOFTWARE.
322
+ */
323
+
324
+#include "qemu/osdep.h"
325
+#include "qemu/main-loop.h"
326
+#include "block/aio-wait.h"
327
+
328
+static void dummy_bh_cb(void *opaque)
329
+{
330
+ /* The point is to make AIO_WAIT_WHILE()'s aio_poll() return */
331
+}
332
+
333
+void aio_wait_kick(AioWait *wait)
334
+{
335
+ /* The barrier (or an atomic op) is in the caller. */
336
+ if (atomic_read(&wait->need_kick)) {
337
+ aio_bh_schedule_oneshot(qemu_get_aio_context(), dummy_bh_cb, NULL);
338
+ }
339
+}
340
diff --git a/util/Makefile.objs b/util/Makefile.objs
341
index XXXXXXX..XXXXXXX 100644
342
--- a/util/Makefile.objs
343
+++ b/util/Makefile.objs
344
@@ -XXX,XX +XXX,XX @@
345
util-obj-y = osdep.o cutils.o unicode.o qemu-timer-common.o
346
util-obj-y += bufferiszero.o
347
util-obj-y += lockcnt.o
348
-util-obj-y += aiocb.o async.o thread-pool.o qemu-timer.o
349
+util-obj-y += aiocb.o async.o aio-wait.o thread-pool.o qemu-timer.o
350
util-obj-y += main-loop.o iohandler.o
351
util-obj-$(CONFIG_POSIX) += aio-posix.o
352
util-obj-$(CONFIG_POSIX) += compatfd.o
353
--
461
--
354
2.13.6
462
2.25.3
355
463
356
464
diff view generated by jsdifflib
1
From: Eric Blake <eblake@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
We are gradually moving away from sector-based interfaces, towards
7
Instead, try to forward the BDRV_REQ_ZERO_WRITE to the protocol driver,
4
byte-based. Update the qcow2 driver accordingly.
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
For now, we are ignoring the 'want_zero' hint. However, it should
11
Unfortunately, the same approach doesn't work for metadata
7
be relatively straightforward to honor the hint as a way to return
12
preallocation, so we'll still set the zero flag there.
8
larger *pnum values when we have consecutive clusters with the same
9
data/zero status but which differ only in having non-consecutive
10
mappings.
11
13
12
Signed-off-by: Eric Blake <eblake@redhat.com>
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>
13
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
17
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
14
Reviewed-by: Fam Zheng <famz@redhat.com>
15
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
18
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
16
---
19
---
17
block/qcow2.c | 24 +++++++++++++-----------
20
block/qcow2.c | 22 +++++++++++++++++++---
18
1 file changed, 13 insertions(+), 11 deletions(-)
21
tests/qemu-iotests/274.out | 4 ++--
22
2 files changed, 21 insertions(+), 5 deletions(-)
19
23
20
diff --git a/block/qcow2.c b/block/qcow2.c
24
diff --git a/block/qcow2.c b/block/qcow2.c
21
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
22
--- a/block/qcow2.c
26
--- a/block/qcow2.c
23
+++ b/block/qcow2.c
27
+++ b/block/qcow2.c
24
@@ -XXX,XX +XXX,XX @@ static void qcow2_join_options(QDict *options, QDict *old_options)
28
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
25
}
29
/* Allocate the data area */
26
}
30
new_file_size = allocation_start +
27
31
nb_new_data_clusters * s->cluster_size;
28
-static int64_t coroutine_fn qcow2_co_get_block_status(BlockDriverState *bs,
32
- /* Image file grows, so @exact does not matter */
29
- int64_t sector_num, int nb_sectors, int *pnum, BlockDriverState **file)
33
- ret = bdrv_co_truncate(bs->file, new_file_size, false, prealloc, 0,
30
+static int coroutine_fn qcow2_co_block_status(BlockDriverState *bs,
34
- errp);
31
+ bool want_zero,
35
+ /*
32
+ int64_t offset, int64_t count,
36
+ * Image file grows, so @exact does not matter.
33
+ int64_t *pnum, int64_t *map,
37
+ *
34
+ BlockDriverState **file)
38
+ * If we need to zero out the new area, try first whether the protocol
35
{
39
+ * driver can already take care of this.
36
BDRVQcow2State *s = bs->opaque;
40
+ */
37
uint64_t cluster_offset;
41
+ if (flags & BDRV_REQ_ZERO_WRITE) {
38
int index_in_cluster, ret;
42
+ ret = bdrv_co_truncate(bs->file, new_file_size, false, prealloc,
39
unsigned int bytes;
43
+ BDRV_REQ_ZERO_WRITE, NULL);
40
- int64_t status = 0;
44
+ if (ret >= 0) {
41
+ int status = 0;
45
+ flags &= ~BDRV_REQ_ZERO_WRITE;
42
46
+ }
43
- bytes = MIN(INT_MAX, nb_sectors * BDRV_SECTOR_SIZE);
47
+ } else {
44
+ bytes = MIN(INT_MAX, count);
48
+ ret = -1;
45
qemu_co_mutex_lock(&s->lock);
49
+ }
46
- ret = qcow2_get_cluster_offset(bs, sector_num << BDRV_SECTOR_BITS, &bytes,
50
+ if (ret < 0) {
47
- &cluster_offset);
51
+ ret = bdrv_co_truncate(bs->file, new_file_size, false, prealloc, 0,
48
+ ret = qcow2_get_cluster_offset(bs, offset, &bytes, &cluster_offset);
52
+ errp);
49
qemu_co_mutex_unlock(&s->lock);
53
+ }
50
if (ret < 0) {
54
if (ret < 0) {
51
return ret;
55
error_prepend(errp, "Failed to resize underlying file: ");
52
}
56
qcow2_free_clusters(bs, allocation_start,
53
57
diff --git a/tests/qemu-iotests/274.out b/tests/qemu-iotests/274.out
54
- *pnum = bytes >> BDRV_SECTOR_BITS;
58
index XXXXXXX..XXXXXXX 100644
55
+ *pnum = bytes;
59
--- a/tests/qemu-iotests/274.out
56
60
+++ b/tests/qemu-iotests/274.out
57
if (cluster_offset != 0 && ret != QCOW2_CLUSTER_COMPRESSED &&
61
@@ -XXX,XX +XXX,XX @@ read 65536/65536 bytes at offset 9437184
58
!s->crypto) {
62
10 MiB (0xa00000) bytes allocated at offset 5 MiB (0x500000)
59
- index_in_cluster = sector_num & (s->cluster_sectors - 1);
63
60
- cluster_offset |= (index_in_cluster << BDRV_SECTOR_BITS);
64
[{ "start": 0, "length": 5242880, "depth": 1, "zero": true, "data": false},
61
+ index_in_cluster = offset & (s->cluster_size - 1);
65
-{ "start": 5242880, "length": 10485760, "depth": 0, "zero": true, "data": false, "offset": 327680}]
62
+ *map = cluster_offset | index_in_cluster;
66
+{ "start": 5242880, "length": 10485760, "depth": 0, "zero": false, "data": true, "offset": 327680}]
63
*file = bs->file->bs;
67
64
- status |= BDRV_BLOCK_OFFSET_VALID | cluster_offset;
68
=== preallocation=full ===
65
+ status |= BDRV_BLOCK_OFFSET_VALID;
69
Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=16777216 cluster_size=65536 lazy_refcounts=off refcount_bits=16
66
}
70
@@ -XXX,XX +XXX,XX @@ read 65536/65536 bytes at offset 11534336
67
if (ret == QCOW2_CLUSTER_ZERO_PLAIN || ret == QCOW2_CLUSTER_ZERO_ALLOC) {
71
4 MiB (0x400000) bytes allocated at offset 8 MiB (0x800000)
68
status |= BDRV_BLOCK_ZERO;
72
69
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_qcow2 = {
73
[{ "start": 0, "length": 8388608, "depth": 1, "zero": true, "data": false},
70
.bdrv_child_perm = bdrv_format_default_perms,
74
-{ "start": 8388608, "length": 4194304, "depth": 0, "zero": true, "data": false, "offset": 327680}]
71
.bdrv_create = qcow2_create,
75
+{ "start": 8388608, "length": 4194304, "depth": 0, "zero": false, "data": true, "offset": 327680}]
72
.bdrv_has_zero_init = bdrv_has_zero_init_1,
76
73
- .bdrv_co_get_block_status = qcow2_co_get_block_status,
77
=== preallocation=off ===
74
+ .bdrv_co_block_status = qcow2_co_block_status,
78
Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=393216 cluster_size=65536 lazy_refcounts=off refcount_bits=16
75
76
.bdrv_co_preadv = qcow2_co_preadv,
77
.bdrv_co_pwritev = qcow2_co_pwritev,
78
--
79
--
79
2.13.6
80
2.25.3
80
81
81
82
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
1
From: Andrzej Jakowski <andrzej.jakowski@linux.intel.com>
2
2
3
We are gradually converting to byte-based interfaces, as they are
3
This patch introduces support for PMR that has been defined as part of NVMe 1.4
4
easier to reason about than sector-based. Convert all uses of
4
spec. User can now specify a pmrdev option that should point to HostMemoryBackend.
5
the cluster size in sectors, along with adding assertions that we
5
pmrdev memory region will subsequently be exposed as PCI BAR 2 in emulated NVMe
6
are not dividing by zero.
6
device. Guest OS can perform mmio read and writes to the PMR region that will stay
7
persistent across system reboot.
7
8
8
Improve some comment grammar while in the area.
9
Signed-off-by: Andrzej Jakowski <andrzej.jakowski@linux.intel.com>
9
10
Reviewed-by: Klaus Jensen <k.jensen@samsung.com>
10
Signed-off-by: Eric Blake <eblake@redhat.com>
11
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
11
Acked-by: Paolo Bonzini <pbonzini@redhat.com>
12
Message-Id: <20200330164656.9348-1-andrzej.jakowski@linux.intel.com>
12
Reviewed-by: Fam Zheng <famz@redhat.com>
13
Reviewed-by: Keith Busch <kbusch@kernel.org>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
---
15
---
15
block/iscsi.c | 56 +++++++++++++++++++++++++++++++++++---------------------
16
hw/block/nvme.h | 2 +
16
1 file changed, 35 insertions(+), 21 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(-)
17
22
18
diff --git a/block/iscsi.c b/block/iscsi.c
23
diff --git a/hw/block/nvme.h b/hw/block/nvme.h
19
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
20
--- a/block/iscsi.c
25
--- a/hw/block/nvme.h
21
+++ b/block/iscsi.c
26
+++ b/hw/block/nvme.h
22
@@ -XXX,XX +XXX,XX @@ typedef struct IscsiLun {
27
@@ -XXX,XX +XXX,XX @@ typedef struct NvmeCtrl {
23
unsigned long *allocmap;
28
uint64_t timestamp_set_qemu_clock_ms; /* QEMU clock time */
24
unsigned long *allocmap_valid;
29
25
long allocmap_size;
30
char *serial;
26
- int cluster_sectors;
31
+ HostMemoryBackend *pmrdev;
27
+ int cluster_size;
32
+
28
bool use_16_for_rw;
33
NvmeNamespace *namespaces;
29
bool write_protected;
34
NvmeSQueue **sq;
30
bool lbpme;
35
NvmeCQueue **cq;
31
@@ -XXX,XX +XXX,XX @@ static int iscsi_allocmap_init(IscsiLun *iscsilun, int open_flags)
36
diff --git a/include/block/nvme.h b/include/block/nvme.h
32
{
37
index XXXXXXX..XXXXXXX 100644
33
iscsi_allocmap_free(iscsilun);
38
--- a/include/block/nvme.h
34
39
+++ b/include/block/nvme.h
35
+ assert(iscsilun->cluster_size);
40
@@ -XXX,XX +XXX,XX @@ typedef struct NvmeBar {
36
iscsilun->allocmap_size =
41
uint64_t acq;
37
- DIV_ROUND_UP(sector_lun2qemu(iscsilun->num_blocks, iscsilun),
42
uint32_t cmbloc;
38
- iscsilun->cluster_sectors);
43
uint32_t cmbsz;
39
+ DIV_ROUND_UP(iscsilun->num_blocks * iscsilun->block_size,
44
+ uint8_t padding[3520]; /* not used by QEMU */
40
+ iscsilun->cluster_size);
45
+ uint32_t pmrcap;
41
46
+ uint32_t pmrctl;
42
iscsilun->allocmap = bitmap_try_new(iscsilun->allocmap_size);
47
+ uint32_t pmrsts;
43
if (!iscsilun->allocmap) {
48
+ uint32_t pmrebs;
44
@@ -XXX,XX +XXX,XX @@ static int iscsi_allocmap_init(IscsiLun *iscsilun, int open_flags)
49
+ uint32_t pmrswtp;
50
+ uint32_t pmrmsc;
51
} NvmeBar;
52
53
enum NvmeCapShift {
54
@@ -XXX,XX +XXX,XX @@ enum NvmeCapShift {
55
CAP_CSS_SHIFT = 37,
56
CAP_MPSMIN_SHIFT = 48,
57
CAP_MPSMAX_SHIFT = 52,
58
+ CAP_PMR_SHIFT = 56,
59
};
60
61
enum NvmeCapMask {
62
@@ -XXX,XX +XXX,XX @@ enum NvmeCapMask {
63
CAP_CSS_MASK = 0xff,
64
CAP_MPSMIN_MASK = 0xf,
65
CAP_MPSMAX_MASK = 0xf,
66
+ CAP_PMR_MASK = 0x1,
67
};
68
69
#define NVME_CAP_MQES(cap) (((cap) >> CAP_MQES_SHIFT) & CAP_MQES_MASK)
70
@@ -XXX,XX +XXX,XX @@ enum NvmeCapMask {
71
<< CAP_MPSMIN_SHIFT)
72
#define NVME_CAP_SET_MPSMAX(cap, val) (cap |= (uint64_t)(val & CAP_MPSMAX_MASK)\
73
<< CAP_MPSMAX_SHIFT)
74
+#define NVME_CAP_SET_PMRS(cap, val) (cap |= (uint64_t)(val & CAP_PMR_MASK)\
75
+ << CAP_PMR_SHIFT)
76
77
enum NvmeCcShift {
78
CC_EN_SHIFT = 0,
79
@@ -XXX,XX +XXX,XX @@ enum NvmeCmbszMask {
80
#define NVME_CMBSZ_GETSIZE(cmbsz) \
81
(NVME_CMBSZ_SZ(cmbsz) * (1 << (12 + 4 * NVME_CMBSZ_SZU(cmbsz))))
82
83
+enum NvmePmrcapShift {
84
+ PMRCAP_RDS_SHIFT = 3,
85
+ PMRCAP_WDS_SHIFT = 4,
86
+ PMRCAP_BIR_SHIFT = 5,
87
+ PMRCAP_PMRTU_SHIFT = 8,
88
+ PMRCAP_PMRWBM_SHIFT = 10,
89
+ PMRCAP_PMRTO_SHIFT = 16,
90
+ PMRCAP_CMSS_SHIFT = 24,
91
+};
92
+
93
+enum NvmePmrcapMask {
94
+ PMRCAP_RDS_MASK = 0x1,
95
+ PMRCAP_WDS_MASK = 0x1,
96
+ PMRCAP_BIR_MASK = 0x7,
97
+ PMRCAP_PMRTU_MASK = 0x3,
98
+ PMRCAP_PMRWBM_MASK = 0xf,
99
+ PMRCAP_PMRTO_MASK = 0xff,
100
+ PMRCAP_CMSS_MASK = 0x1,
101
+};
102
+
103
+#define NVME_PMRCAP_RDS(pmrcap) \
104
+ ((pmrcap >> PMRCAP_RDS_SHIFT) & PMRCAP_RDS_MASK)
105
+#define NVME_PMRCAP_WDS(pmrcap) \
106
+ ((pmrcap >> PMRCAP_WDS_SHIFT) & PMRCAP_WDS_MASK)
107
+#define NVME_PMRCAP_BIR(pmrcap) \
108
+ ((pmrcap >> PMRCAP_BIR_SHIFT) & PMRCAP_BIR_MASK)
109
+#define NVME_PMRCAP_PMRTU(pmrcap) \
110
+ ((pmrcap >> PMRCAP_PMRTU_SHIFT) & PMRCAP_PMRTU_MASK)
111
+#define NVME_PMRCAP_PMRWBM(pmrcap) \
112
+ ((pmrcap >> PMRCAP_PMRWBM_SHIFT) & PMRCAP_PMRWBM_MASK)
113
+#define NVME_PMRCAP_PMRTO(pmrcap) \
114
+ ((pmrcap >> PMRCAP_PMRTO_SHIFT) & PMRCAP_PMRTO_MASK)
115
+#define NVME_PMRCAP_CMSS(pmrcap) \
116
+ ((pmrcap >> PMRCAP_CMSS_SHIFT) & PMRCAP_CMSS_MASK)
117
+
118
+#define NVME_PMRCAP_SET_RDS(pmrcap, val) \
119
+ (pmrcap |= (uint64_t)(val & PMRCAP_RDS_MASK) << PMRCAP_RDS_SHIFT)
120
+#define NVME_PMRCAP_SET_WDS(pmrcap, val) \
121
+ (pmrcap |= (uint64_t)(val & PMRCAP_WDS_MASK) << PMRCAP_WDS_SHIFT)
122
+#define NVME_PMRCAP_SET_BIR(pmrcap, val) \
123
+ (pmrcap |= (uint64_t)(val & PMRCAP_BIR_MASK) << PMRCAP_BIR_SHIFT)
124
+#define NVME_PMRCAP_SET_PMRTU(pmrcap, val) \
125
+ (pmrcap |= (uint64_t)(val & PMRCAP_PMRTU_MASK) << PMRCAP_PMRTU_SHIFT)
126
+#define NVME_PMRCAP_SET_PMRWBM(pmrcap, val) \
127
+ (pmrcap |= (uint64_t)(val & PMRCAP_PMRWBM_MASK) << PMRCAP_PMRWBM_SHIFT)
128
+#define NVME_PMRCAP_SET_PMRTO(pmrcap, val) \
129
+ (pmrcap |= (uint64_t)(val & PMRCAP_PMRTO_MASK) << PMRCAP_PMRTO_SHIFT)
130
+#define NVME_PMRCAP_SET_CMSS(pmrcap, val) \
131
+ (pmrcap |= (uint64_t)(val & PMRCAP_CMSS_MASK) << PMRCAP_CMSS_SHIFT)
132
+
133
+enum NvmePmrctlShift {
134
+ PMRCTL_EN_SHIFT = 0,
135
+};
136
+
137
+enum NvmePmrctlMask {
138
+ PMRCTL_EN_MASK = 0x1,
139
+};
140
+
141
+#define NVME_PMRCTL_EN(pmrctl) ((pmrctl >> PMRCTL_EN_SHIFT) & PMRCTL_EN_MASK)
142
+
143
+#define NVME_PMRCTL_SET_EN(pmrctl, val) \
144
+ (pmrctl |= (uint64_t)(val & PMRCTL_EN_MASK) << PMRCTL_EN_SHIFT)
145
+
146
+enum NvmePmrstsShift {
147
+ PMRSTS_ERR_SHIFT = 0,
148
+ PMRSTS_NRDY_SHIFT = 8,
149
+ PMRSTS_HSTS_SHIFT = 9,
150
+ PMRSTS_CBAI_SHIFT = 12,
151
+};
152
+
153
+enum NvmePmrstsMask {
154
+ PMRSTS_ERR_MASK = 0xff,
155
+ PMRSTS_NRDY_MASK = 0x1,
156
+ PMRSTS_HSTS_MASK = 0x7,
157
+ PMRSTS_CBAI_MASK = 0x1,
158
+};
159
+
160
+#define NVME_PMRSTS_ERR(pmrsts) \
161
+ ((pmrsts >> PMRSTS_ERR_SHIFT) & PMRSTS_ERR_MASK)
162
+#define NVME_PMRSTS_NRDY(pmrsts) \
163
+ ((pmrsts >> PMRSTS_NRDY_SHIFT) & PMRSTS_NRDY_MASK)
164
+#define NVME_PMRSTS_HSTS(pmrsts) \
165
+ ((pmrsts >> PMRSTS_HSTS_SHIFT) & PMRSTS_HSTS_MASK)
166
+#define NVME_PMRSTS_CBAI(pmrsts) \
167
+ ((pmrsts >> PMRSTS_CBAI_SHIFT) & PMRSTS_CBAI_MASK)
168
+
169
+#define NVME_PMRSTS_SET_ERR(pmrsts, val) \
170
+ (pmrsts |= (uint64_t)(val & PMRSTS_ERR_MASK) << PMRSTS_ERR_SHIFT)
171
+#define NVME_PMRSTS_SET_NRDY(pmrsts, val) \
172
+ (pmrsts |= (uint64_t)(val & PMRSTS_NRDY_MASK) << PMRSTS_NRDY_SHIFT)
173
+#define NVME_PMRSTS_SET_HSTS(pmrsts, val) \
174
+ (pmrsts |= (uint64_t)(val & PMRSTS_HSTS_MASK) << PMRSTS_HSTS_SHIFT)
175
+#define NVME_PMRSTS_SET_CBAI(pmrsts, val) \
176
+ (pmrsts |= (uint64_t)(val & PMRSTS_CBAI_MASK) << PMRSTS_CBAI_SHIFT)
177
+
178
+enum NvmePmrebsShift {
179
+ PMREBS_PMRSZU_SHIFT = 0,
180
+ PMREBS_RBB_SHIFT = 4,
181
+ PMREBS_PMRWBZ_SHIFT = 8,
182
+};
183
+
184
+enum NvmePmrebsMask {
185
+ PMREBS_PMRSZU_MASK = 0xf,
186
+ PMREBS_RBB_MASK = 0x1,
187
+ PMREBS_PMRWBZ_MASK = 0xffffff,
188
+};
189
+
190
+#define NVME_PMREBS_PMRSZU(pmrebs) \
191
+ ((pmrebs >> PMREBS_PMRSZU_SHIFT) & PMREBS_PMRSZU_MASK)
192
+#define NVME_PMREBS_RBB(pmrebs) \
193
+ ((pmrebs >> PMREBS_RBB_SHIFT) & PMREBS_RBB_MASK)
194
+#define NVME_PMREBS_PMRWBZ(pmrebs) \
195
+ ((pmrebs >> PMREBS_PMRWBZ_SHIFT) & PMREBS_PMRWBZ_MASK)
196
+
197
+#define NVME_PMREBS_SET_PMRSZU(pmrebs, val) \
198
+ (pmrebs |= (uint64_t)(val & PMREBS_PMRSZU_MASK) << PMREBS_PMRSZU_SHIFT)
199
+#define NVME_PMREBS_SET_RBB(pmrebs, val) \
200
+ (pmrebs |= (uint64_t)(val & PMREBS_RBB_MASK) << PMREBS_RBB_SHIFT)
201
+#define NVME_PMREBS_SET_PMRWBZ(pmrebs, val) \
202
+ (pmrebs |= (uint64_t)(val & PMREBS_PMRWBZ_MASK) << PMREBS_PMRWBZ_SHIFT)
203
+
204
+enum NvmePmrswtpShift {
205
+ PMRSWTP_PMRSWTU_SHIFT = 0,
206
+ PMRSWTP_PMRSWTV_SHIFT = 8,
207
+};
208
+
209
+enum NvmePmrswtpMask {
210
+ PMRSWTP_PMRSWTU_MASK = 0xf,
211
+ PMRSWTP_PMRSWTV_MASK = 0xffffff,
212
+};
213
+
214
+#define NVME_PMRSWTP_PMRSWTU(pmrswtp) \
215
+ ((pmrswtp >> PMRSWTP_PMRSWTU_SHIFT) & PMRSWTP_PMRSWTU_MASK)
216
+#define NVME_PMRSWTP_PMRSWTV(pmrswtp) \
217
+ ((pmrswtp >> PMRSWTP_PMRSWTV_SHIFT) & PMRSWTP_PMRSWTV_MASK)
218
+
219
+#define NVME_PMRSWTP_SET_PMRSWTU(pmrswtp, val) \
220
+ (pmrswtp |= (uint64_t)(val & PMRSWTP_PMRSWTU_MASK) << PMRSWTP_PMRSWTU_SHIFT)
221
+#define NVME_PMRSWTP_SET_PMRSWTV(pmrswtp, val) \
222
+ (pmrswtp |= (uint64_t)(val & PMRSWTP_PMRSWTV_MASK) << PMRSWTP_PMRSWTV_SHIFT)
223
+
224
+enum NvmePmrmscShift {
225
+ PMRMSC_CMSE_SHIFT = 1,
226
+ PMRMSC_CBA_SHIFT = 12,
227
+};
228
+
229
+enum NvmePmrmscMask {
230
+ PMRMSC_CMSE_MASK = 0x1,
231
+ PMRMSC_CBA_MASK = 0xfffffffffffff,
232
+};
233
+
234
+#define NVME_PMRMSC_CMSE(pmrmsc) \
235
+ ((pmrmsc >> PMRMSC_CMSE_SHIFT) & PMRMSC_CMSE_MASK)
236
+#define NVME_PMRMSC_CBA(pmrmsc) \
237
+ ((pmrmsc >> PMRMSC_CBA_SHIFT) & PMRMSC_CBA_MASK)
238
+
239
+#define NVME_PMRMSC_SET_CMSE(pmrmsc, val) \
240
+ (pmrmsc |= (uint64_t)(val & PMRMSC_CMSE_MASK) << PMRMSC_CMSE_SHIFT)
241
+#define NVME_PMRMSC_SET_CBA(pmrmsc, val) \
242
+ (pmrmsc |= (uint64_t)(val & PMRMSC_CBA_MASK) << PMRMSC_CBA_SHIFT)
243
+
244
typedef struct NvmeCmd {
245
uint8_t opcode;
246
uint8_t fuse;
247
diff --git a/hw/block/nvme.c b/hw/block/nvme.c
248
index XXXXXXX..XXXXXXX 100644
249
--- a/hw/block/nvme.c
250
+++ b/hw/block/nvme.c
251
@@ -XXX,XX +XXX,XX @@
252
* -drive file=<file>,if=none,id=<drive_id>
253
* -device nvme,drive=<drive_id>,serial=<serial>,id=<id[optional]>, \
254
* cmb_size_mb=<cmb_size_mb[optional]>, \
255
+ * [pmrdev=<mem_backend_file_id>,] \
256
* num_queues=<N[optional]>
257
*
258
* Note cmb_size_mb denotes size of CMB in MB. CMB is assumed to be at
259
* offset 0 in BAR2 and supports only WDS, RDS and SQS for now.
260
+ *
261
+ * cmb_size_mb= and pmrdev= options are mutually exclusive due to limitation
262
+ * in available BAR's. cmb_size_mb= will take precedence over pmrdev= when
263
+ * both provided.
264
+ * Enabling pmr emulation can be achieved by pointing to memory-backend-file.
265
+ * For example:
266
+ * -object memory-backend-file,id=<mem_id>,share=on,mem-path=<file_path>, \
267
+ * size=<size> .... -device nvme,...,pmrdev=<mem_id>
268
*/
269
270
#include "qemu/osdep.h"
271
@@ -XXX,XX +XXX,XX @@
272
#include "sysemu/sysemu.h"
273
#include "qapi/error.h"
274
#include "qapi/visitor.h"
275
+#include "sysemu/hostmem.h"
276
#include "sysemu/block-backend.h"
277
+#include "exec/ram_addr.h"
278
279
#include "qemu/log.h"
280
#include "qemu/module.h"
281
@@ -XXX,XX +XXX,XX @@ static void nvme_write_bar(NvmeCtrl *n, hwaddr offset, uint64_t data,
282
NVME_GUEST_ERR(nvme_ub_mmiowr_cmbsz_readonly,
283
"invalid write to read only CMBSZ, ignored");
284
return;
285
+ case 0xE00: /* PMRCAP */
286
+ NVME_GUEST_ERR(nvme_ub_mmiowr_pmrcap_readonly,
287
+ "invalid write to PMRCAP register, ignored");
288
+ return;
289
+ case 0xE04: /* TODO PMRCTL */
290
+ break;
291
+ case 0xE08: /* PMRSTS */
292
+ NVME_GUEST_ERR(nvme_ub_mmiowr_pmrsts_readonly,
293
+ "invalid write to PMRSTS register, ignored");
294
+ return;
295
+ case 0xE0C: /* PMREBS */
296
+ NVME_GUEST_ERR(nvme_ub_mmiowr_pmrebs_readonly,
297
+ "invalid write to PMREBS register, ignored");
298
+ return;
299
+ case 0xE10: /* PMRSWTP */
300
+ NVME_GUEST_ERR(nvme_ub_mmiowr_pmrswtp_readonly,
301
+ "invalid write to PMRSWTP register, ignored");
302
+ return;
303
+ case 0xE14: /* TODO PMRMSC */
304
+ break;
305
default:
306
NVME_GUEST_ERR(nvme_ub_mmiowr_invalid,
307
"invalid MMIO write,"
308
@@ -XXX,XX +XXX,XX @@ static uint64_t nvme_mmio_read(void *opaque, hwaddr addr, unsigned size)
45
}
309
}
46
310
47
if (open_flags & BDRV_O_NOCACHE) {
311
if (addr < sizeof(n->bar)) {
48
- /* in case that cache.direct = on all allocmap entries are
312
+ /*
49
+ /* when cache.direct = on all allocmap entries are
313
+ * When PMRWBM bit 1 is set then read from
50
* treated as invalid to force a relookup of the block
314
+ * from PMRSTS should ensure prior writes
51
* status on every read request */
315
+ * made it to persistent media
52
return 0;
316
+ */
53
@@ -XXX,XX +XXX,XX @@ iscsi_allocmap_update(IscsiLun *iscsilun, int64_t sector_num,
317
+ if (addr == 0xE08 &&
54
int nb_sectors, bool allocated, bool valid)
318
+ (NVME_PMRCAP_PMRWBM(n->bar.pmrcap) & 0x02)) {
55
{
319
+ qemu_ram_writeback(n->pmrdev->mr.ram_block,
56
int64_t cl_num_expanded, nb_cls_expanded, cl_num_shrunk, nb_cls_shrunk;
320
+ 0, n->pmrdev->size);
57
+ int cluster_sectors = iscsilun->cluster_size >> BDRV_SECTOR_BITS;
321
+ }
58
322
memcpy(&val, ptr + addr, size);
59
if (iscsilun->allocmap == NULL) {
323
} else {
324
NVME_GUEST_ERR(nvme_ub_mmiord_invalid_ofs,
325
@@ -XXX,XX +XXX,XX @@ static void nvme_realize(PCIDevice *pci_dev, Error **errp)
326
error_setg(errp, "serial property not set");
60
return;
327
return;
61
}
328
}
62
/* expand to entirely contain all affected clusters */
329
+
63
- cl_num_expanded = sector_num / iscsilun->cluster_sectors;
330
+ if (!n->cmb_size_mb && n->pmrdev) {
64
+ assert(cluster_sectors);
331
+ if (host_memory_backend_is_mapped(n->pmrdev)) {
65
+ cl_num_expanded = sector_num / cluster_sectors;
332
+ char *path = object_get_canonical_path_component(OBJECT(n->pmrdev));
66
nb_cls_expanded = DIV_ROUND_UP(sector_num + nb_sectors,
333
+ error_setg(errp, "can't use already busy memdev: %s", path);
67
- iscsilun->cluster_sectors) - cl_num_expanded;
334
+ g_free(path);
68
+ cluster_sectors) - cl_num_expanded;
335
+ return;
69
/* shrink to touch only completely contained clusters */
336
+ }
70
- cl_num_shrunk = DIV_ROUND_UP(sector_num, iscsilun->cluster_sectors);
337
+
71
- nb_cls_shrunk = (sector_num + nb_sectors) / iscsilun->cluster_sectors
338
+ if (!is_power_of_2(n->pmrdev->size)) {
72
+ cl_num_shrunk = DIV_ROUND_UP(sector_num, cluster_sectors);
339
+ error_setg(errp, "pmr backend size needs to be power of 2 in size");
73
+ nb_cls_shrunk = (sector_num + nb_sectors) / cluster_sectors
340
+ return;
74
- cl_num_shrunk;
341
+ }
75
if (allocated) {
342
+
76
bitmap_set(iscsilun->allocmap, cl_num_expanded, nb_cls_expanded);
343
+ host_memory_backend_set_mapped(n->pmrdev, true);
77
@@ -XXX,XX +XXX,XX @@ iscsi_allocmap_is_allocated(IscsiLun *iscsilun, int64_t sector_num,
344
+ }
78
if (iscsilun->allocmap == NULL) {
345
+
79
return true;
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);
80
}
398
}
81
- size = DIV_ROUND_UP(sector_num + nb_sectors, iscsilun->cluster_sectors);
399
82
+ assert(iscsilun->cluster_size);
400
for (i = 0; i < n->num_namespaces; i++) {
83
+ size = DIV_ROUND_UP(sector_num + nb_sectors,
401
@@ -XXX,XX +XXX,XX @@ static void nvme_exit(PCIDevice *pci_dev)
84
+ iscsilun->cluster_size >> BDRV_SECTOR_BITS);
402
if (n->cmb_size_mb) {
85
return !(find_next_bit(iscsilun->allocmap, size,
403
g_free(n->cmbuf);
86
- sector_num / iscsilun->cluster_sectors) == size);
404
}
87
+ sector_num * BDRV_SECTOR_SIZE /
405
+
88
+ iscsilun->cluster_size) == size);
406
+ if (n->pmrdev) {
407
+ host_memory_backend_set_mapped(n->pmrdev, false);
408
+ }
409
msix_uninit_exclusive_bar(pci_dev);
89
}
410
}
90
411
91
static inline bool iscsi_allocmap_is_valid(IscsiLun *iscsilun,
412
static Property nvme_props[] = {
92
@@ -XXX,XX +XXX,XX @@ static inline bool iscsi_allocmap_is_valid(IscsiLun *iscsilun,
413
DEFINE_BLOCK_PROPERTIES(NvmeCtrl, conf),
93
if (iscsilun->allocmap_valid == NULL) {
414
+ DEFINE_PROP_LINK("pmrdev", NvmeCtrl, pmrdev, TYPE_MEMORY_BACKEND,
94
return false;
415
+ HostMemoryBackend *),
95
}
416
DEFINE_PROP_STRING("serial", NvmeCtrl, serial),
96
- size = DIV_ROUND_UP(sector_num + nb_sectors, iscsilun->cluster_sectors);
417
DEFINE_PROP_UINT32("cmb_size_mb", NvmeCtrl, cmb_size_mb, 0),
97
+ assert(iscsilun->cluster_size);
418
DEFINE_PROP_UINT32("num_queues", NvmeCtrl, num_queues, 64),
98
+ size = DIV_ROUND_UP(sector_num + nb_sectors,
419
diff --git a/hw/block/Makefile.objs b/hw/block/Makefile.objs
99
+ iscsilun->cluster_size >> BDRV_SECTOR_BITS);
420
index XXXXXXX..XXXXXXX 100644
100
return (find_next_zero_bit(iscsilun->allocmap_valid, size,
421
--- a/hw/block/Makefile.objs
101
- sector_num / iscsilun->cluster_sectors) == size);
422
+++ b/hw/block/Makefile.objs
102
+ sector_num * BDRV_SECTOR_SIZE /
423
@@ -XXX,XX +XXX,XX @@ common-obj-$(CONFIG_PFLASH_CFI02) += pflash_cfi02.o
103
+ iscsilun->cluster_size) == size);
424
common-obj-$(CONFIG_XEN) += xen-block.o
104
}
425
common-obj-$(CONFIG_ECC) += ecc.o
105
426
common-obj-$(CONFIG_ONENAND) += onenand.o
106
static int coroutine_fn
427
-common-obj-$(CONFIG_NVME_PCI) += nvme.o
107
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn iscsi_co_readv(BlockDriverState *bs,
428
common-obj-$(CONFIG_SWIM) += swim.o
108
BlockDriverState *file;
429
109
/* check the block status from the beginning of the cluster
430
common-obj-$(CONFIG_SH4) += tc58128.o
110
* containing the start sector */
431
111
- int64_t ret = iscsi_co_get_block_status(bs,
432
obj-$(CONFIG_VIRTIO_BLK) += virtio-blk.o
112
- sector_num - sector_num % iscsilun->cluster_sectors,
433
obj-$(CONFIG_VHOST_USER_BLK) += vhost-user-blk.o
113
- BDRV_REQUEST_MAX_SECTORS, &pnum, &file);
434
+obj-$(CONFIG_NVME_PCI) += nvme.o
114
+ int cluster_sectors = iscsilun->cluster_size >> BDRV_SECTOR_BITS;
435
115
+ int head;
436
obj-y += dataplane/
116
+ int64_t ret;
437
diff --git a/hw/block/trace-events b/hw/block/trace-events
117
+
438
index XXXXXXX..XXXXXXX 100644
118
+ assert(cluster_sectors);
439
--- a/hw/block/trace-events
119
+ head = sector_num % cluster_sectors;
440
+++ b/hw/block/trace-events
120
+ ret = iscsi_co_get_block_status(bs, sector_num - head,
441
@@ -XXX,XX +XXX,XX @@ nvme_ub_mmiowr_ssreset_w1c_unsupported(void) "attempted to W1C CSTS.NSSRO but CA
121
+ BDRV_REQUEST_MAX_SECTORS, &pnum,
442
nvme_ub_mmiowr_ssreset_unsupported(void) "attempted NVM subsystem reset but CAP.NSSRS is zero (not supported)"
122
+ &file);
443
nvme_ub_mmiowr_cmbloc_reserved(void) "invalid write to reserved CMBLOC when CMBSZ is zero, ignored"
123
if (ret < 0) {
444
nvme_ub_mmiowr_cmbsz_readonly(void) "invalid write to read only CMBSZ, ignored"
124
return ret;
445
+nvme_ub_mmiowr_pmrcap_readonly(void) "invalid write to read only PMRCAP, ignored"
125
}
446
+nvme_ub_mmiowr_pmrsts_readonly(void) "invalid write to read only PMRSTS, ignored"
126
/* if the whole request falls into an unallocated area we can avoid
447
+nvme_ub_mmiowr_pmrebs_readonly(void) "invalid write to read only PMREBS, ignored"
127
- * to read and directly return zeroes instead */
448
+nvme_ub_mmiowr_pmrswtp_readonly(void) "invalid write to read only PMRSWTP, ignored"
128
- if (ret & BDRV_BLOCK_ZERO &&
449
nvme_ub_mmiowr_invalid(uint64_t offset, uint64_t data) "invalid MMIO write, offset=0x%"PRIx64", data=0x%"PRIx64""
129
- pnum >= nb_sectors + sector_num % iscsilun->cluster_sectors) {
450
nvme_ub_mmiord_misaligned32(uint64_t offset) "MMIO read not 32-bit aligned, offset=0x%"PRIx64""
130
+ * reading and directly return zeroes instead */
451
nvme_ub_mmiord_toosmall(uint64_t offset) "MMIO read smaller than 32-bits, offset=0x%"PRIx64""
131
+ if (ret & BDRV_BLOCK_ZERO && pnum >= nb_sectors + head) {
132
qemu_iovec_memset(iov, 0, 0x00, iov->size);
133
return 0;
134
}
135
@@ -XXX,XX +XXX,XX @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags,
136
* reasonable size */
137
if (iscsilun->bl.opt_unmap_gran * iscsilun->block_size >= 4 * 1024 &&
138
iscsilun->bl.opt_unmap_gran * iscsilun->block_size <= 16 * 1024 * 1024) {
139
- iscsilun->cluster_sectors = (iscsilun->bl.opt_unmap_gran *
140
- iscsilun->block_size) >> BDRV_SECTOR_BITS;
141
+ iscsilun->cluster_size = iscsilun->bl.opt_unmap_gran *
142
+ iscsilun->block_size;
143
if (iscsilun->lbprz) {
144
ret = iscsi_allocmap_init(iscsilun, bs->open_flags);
145
}
146
@@ -XXX,XX +XXX,XX @@ static int iscsi_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
147
{
148
IscsiLun *iscsilun = bs->opaque;
149
bdi->unallocated_blocks_are_zero = iscsilun->lbprz;
150
- bdi->cluster_size = iscsilun->cluster_sectors * BDRV_SECTOR_SIZE;
151
+ bdi->cluster_size = iscsilun->cluster_size;
152
return 0;
153
}
154
155
--
452
--
156
2.13.6
453
2.25.3
157
454
158
455
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
1
The QMP handler qmp_object_add() and the implementation of --object in
2
qemu-storage-daemon can share most of the code. Currently,
3
qemu-storage-daemon calls qmp_object_add(), but this is not correct
4
because different visitors need to be used.
2
5
3
We are gradually moving away from sector-based interfaces, towards
6
As a first step towards a fix, make qmp_object_add() a wrapper around a
4
byte-based. Update the parallels driver accordingly. Note that
7
new function user_creatable_add_dict() that can get an additional
5
the internal function block_status() is still sector-based, because
8
parameter. The handling of "props" is only required for compatibility
6
it is still in use by other sector-based functions; but that's okay
9
and not required for the qemu-storage-daemon command line, so it stays
7
because request_alignment is 512 as a result of those functions.
10
in qmp_object_add().
8
For now, no optimizations are added based on the mapping hint.
9
11
10
Signed-off-by: Eric Blake <eblake@redhat.com>
11
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
12
Reviewed-by: Fam Zheng <famz@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
---
13
---
15
block/parallels.c | 22 +++++++++++++++-------
14
include/qom/object_interfaces.h | 12 ++++++++++++
16
1 file changed, 15 insertions(+), 7 deletions(-)
15
qom/object_interfaces.c | 27 +++++++++++++++++++++++++++
16
qom/qom-qmp-cmds.c | 24 +-----------------------
17
3 files changed, 40 insertions(+), 23 deletions(-)
17
18
18
diff --git a/block/parallels.c b/block/parallels.c
19
diff --git a/include/qom/object_interfaces.h b/include/qom/object_interfaces.h
19
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
20
--- a/block/parallels.c
21
--- a/include/qom/object_interfaces.h
21
+++ b/block/parallels.c
22
+++ b/include/qom/object_interfaces.h
22
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int parallels_co_flush_to_os(BlockDriverState *bs)
23
@@ -XXX,XX +XXX,XX @@ Object *user_creatable_add_type(const char *type, const char *id,
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;
23
}
56
}
24
57
25
58
+void user_creatable_add_dict(QDict *qdict, Error **errp)
26
-static int64_t coroutine_fn parallels_co_get_block_status(BlockDriverState *bs,
59
+{
27
- int64_t sector_num, int nb_sectors, int *pnum, BlockDriverState **file)
60
+ Visitor *v;
28
+static int coroutine_fn parallels_co_block_status(BlockDriverState *bs,
61
+ Object *obj;
29
+ bool want_zero,
62
+ g_autofree char *type = NULL;
30
+ int64_t offset,
63
+ g_autofree char *id = NULL;
31
+ int64_t bytes,
64
+
32
+ int64_t *pnum,
65
+ type = g_strdup(qdict_get_try_str(qdict, "qom-type"));
33
+ int64_t *map,
66
+ if (!type) {
34
+ BlockDriverState **file)
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)
35
{
86
{
36
BDRVParallelsState *s = bs->opaque;
87
diff --git a/qom/qom-qmp-cmds.c b/qom/qom-qmp-cmds.c
37
- int64_t offset;
88
index XXXXXXX..XXXXXXX 100644
38
+ int count;
89
--- a/qom/qom-qmp-cmds.c
39
90
+++ b/qom/qom-qmp-cmds.c
40
+ assert(QEMU_IS_ALIGNED(offset | bytes, BDRV_SECTOR_SIZE));
91
@@ -XXX,XX +XXX,XX @@
41
qemu_co_mutex_lock(&s->lock);
92
#include "qapi/qapi-commands-qom.h"
42
- offset = block_status(s, sector_num, nb_sectors, pnum);
93
#include "qapi/qmp/qdict.h"
43
+ offset = block_status(s, offset >> BDRV_SECTOR_BITS,
94
#include "qapi/qmp/qerror.h"
44
+ bytes >> BDRV_SECTOR_BITS, &count);
95
-#include "qapi/qobject-input-visitor.h"
45
qemu_co_mutex_unlock(&s->lock);
96
#include "qemu/cutils.h"
46
97
#include "qom/object_interfaces.h"
47
+ *pnum = count * BDRV_SECTOR_SIZE;
98
#include "qom/qom-qobject.h"
48
if (offset < 0) {
99
@@ -XXX,XX +XXX,XX @@ void qmp_object_add(QDict *qdict, QObject **ret_data, Error **errp)
49
return 0;
100
{
101
QObject *props;
102
QDict *pdict;
103
- Visitor *v;
104
- Object *obj;
105
- g_autofree char *type = NULL;
106
- g_autofree char *id = NULL;
107
-
108
- type = g_strdup(qdict_get_try_str(qdict, "qom-type"));
109
- if (!type) {
110
- error_setg(errp, QERR_MISSING_PARAMETER, "qom-type");
111
- return;
112
- }
113
- qdict_del(qdict, "qom-type");
114
-
115
- id = g_strdup(qdict_get_try_str(qdict, "id"));
116
- if (!id) {
117
- error_setg(errp, QERR_MISSING_PARAMETER, "id");
118
- return;
119
- }
120
- qdict_del(qdict, "id");
121
122
props = qdict_get(qdict, "props");
123
if (props) {
124
@@ -XXX,XX +XXX,XX @@ void qmp_object_add(QDict *qdict, QObject **ret_data, Error **errp)
125
qobject_unref(pdict);
50
}
126
}
51
127
52
+ *map = offset * BDRV_SECTOR_SIZE;
128
- v = qobject_input_visitor_new(QOBJECT(qdict));
53
*file = bs->file->bs;
129
- obj = user_creatable_add_type(type, id, qdict, v, errp);
54
- return (offset << BDRV_SECTOR_BITS) |
130
- visit_free(v);
55
- BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID;
131
- object_unref(obj);
56
+ return BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID;
132
+ user_creatable_add_dict(qdict, errp);
57
}
133
}
58
134
59
static coroutine_fn int parallels_co_writev(BlockDriverState *bs,
135
void qmp_object_del(const char *id, Error **errp)
60
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_parallels = {
61
.bdrv_open        = parallels_open,
62
.bdrv_close        = parallels_close,
63
.bdrv_child_perm = bdrv_format_default_perms,
64
- .bdrv_co_get_block_status = parallels_co_get_block_status,
65
+ .bdrv_co_block_status = parallels_co_block_status,
66
.bdrv_has_zero_init = bdrv_has_zero_init_1,
67
.bdrv_co_flush_to_os = parallels_co_flush_to_os,
68
.bdrv_co_readv = parallels_co_readv,
69
--
136
--
70
2.13.6
137
2.25.3
71
138
72
139
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. Update the gluster driver accordingly.
6
expects a QDict where all properties already have the QType that matches
7
the data type required by the QOM object type.
5
8
6
In want_zero mode, we continue to report fine-grained hole
9
Change the --object implementation in qemu-storage-daemon so that it
7
information (the caller wants as much mapping detail as possible);
10
doesn't call qmp_object_add(), but calls user_creatable_add_dict()
8
but when not in that mode, the caller prefers larger *pnum and
11
directly instead and pass it a new keyval boolean that decides which
9
merely cares about what offsets are allocated at this layer, rather
12
visitor must be used.
10
than where the holes live. Since holes still read as zeroes at
11
this layer (rather than deferring to a backing layer), we can take
12
the shortcut of skipping find_allocation(), and merely state that
13
all bytes are allocated.
14
13
15
We can also drop redundant bounds checks that are already
14
Reported-by: Coiby Xu <coiby.xu@gmail.com>
16
guaranteed by the block layer.
17
18
Signed-off-by: Eric Blake <eblake@redhat.com>
19
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
20
Reviewed-by: Fam Zheng <famz@redhat.com>
21
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
22
---
16
---
23
block/gluster.c | 70 ++++++++++++++++++++++++++++-----------------------------
17
include/qom/object_interfaces.h | 6 +++++-
24
1 file changed, 34 insertions(+), 36 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(-)
25
22
26
diff --git a/block/gluster.c b/block/gluster.c
23
diff --git a/include/qom/object_interfaces.h b/include/qom/object_interfaces.h
27
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
28
--- a/block/gluster.c
25
--- a/include/qom/object_interfaces.h
29
+++ b/block/gluster.c
26
+++ b/include/qom/object_interfaces.h
30
@@ -XXX,XX +XXX,XX @@ exit:
27
@@ -XXX,XX +XXX,XX @@ Object *user_creatable_add_type(const char *type, const char *id,
28
/**
29
* user_creatable_add_dict:
30
* @qdict: the object definition
31
+ * @keyval: if true, use a keyval visitor for processing @qdict (i.e.
32
+ * assume that all @qdict values are strings); otherwise, use
33
+ * the normal QObject visitor (i.e. assume all @qdict values
34
+ * have the QType expected by the QOM object type)
35
* @errp: if an error occurs, a pointer to an area to store the error
36
*
37
* Create an instance of the user creatable object that is defined by
38
@@ -XXX,XX +XXX,XX @@ Object *user_creatable_add_type(const char *type, const char *id,
39
* ID from the key 'id'. The remaining entries in @qdict are used to
40
* initialize the object properties.
41
*/
42
-void user_creatable_add_dict(QDict *qdict, Error **errp);
43
+void user_creatable_add_dict(QDict *qdict, bool keyval, Error **errp);
44
45
/**
46
* user_creatable_add_opts:
47
diff --git a/qemu-storage-daemon.c b/qemu-storage-daemon.c
48
index XXXXXXX..XXXXXXX 100644
49
--- a/qemu-storage-daemon.c
50
+++ b/qemu-storage-daemon.c
51
@@ -XXX,XX +XXX,XX @@ static void process_options(int argc, char *argv[])
52
QemuOpts *opts;
53
const char *type;
54
QDict *args;
55
- QObject *ret_data = NULL;
56
57
/* FIXME The keyval parser rejects 'help' arguments, so we must
58
* unconditionall try QemuOpts first. */
59
@@ -XXX,XX +XXX,XX @@ static void process_options(int argc, char *argv[])
60
qemu_opts_del(opts);
61
62
args = keyval_parse(optarg, "qom-type", &error_fatal);
63
- qmp_object_add(args, &ret_data, &error_fatal);
64
+ user_creatable_add_dict(args, true, &error_fatal);
65
qobject_unref(args);
66
- qobject_unref(ret_data);
67
break;
68
}
69
default:
70
diff --git a/qom/object_interfaces.c b/qom/object_interfaces.c
71
index XXXXXXX..XXXXXXX 100644
72
--- a/qom/object_interfaces.c
73
+++ b/qom/object_interfaces.c
74
@@ -XXX,XX +XXX,XX @@ out:
75
return obj;
31
}
76
}
32
77
33
/*
78
-void user_creatable_add_dict(QDict *qdict, Error **errp)
34
- * Returns the allocation status of the specified sectors.
79
+void user_creatable_add_dict(QDict *qdict, bool keyval, Error **errp)
35
+ * Returns the allocation status of the specified offset.
36
*
37
- * If 'sector_num' is beyond the end of the disk image the return value is 0
38
- * and 'pnum' is set to 0.
39
+ * The block layer guarantees 'offset' and 'bytes' are within bounds.
40
*
41
- * 'pnum' is set to the number of sectors (including and immediately following
42
- * the specified sector) that are known to be in the same
43
+ * 'pnum' is set to the number of bytes (including and immediately following
44
+ * the specified offset) that are known to be in the same
45
* allocated/unallocated state.
46
*
47
- * 'nb_sectors' is the max value 'pnum' should be set to. If nb_sectors goes
48
- * beyond the end of the disk image it will be clamped.
49
+ * 'bytes' is the max value 'pnum' should be set to.
50
*
51
- * (Based on raw_co_get_block_status() from file-posix.c.)
52
+ * (Based on raw_co_block_status() from file-posix.c.)
53
*/
54
-static int64_t coroutine_fn qemu_gluster_co_get_block_status(
55
- BlockDriverState *bs, int64_t sector_num, int nb_sectors, int *pnum,
56
- BlockDriverState **file)
57
+static int coroutine_fn qemu_gluster_co_block_status(BlockDriverState *bs,
58
+ bool want_zero,
59
+ int64_t offset,
60
+ int64_t bytes,
61
+ int64_t *pnum,
62
+ int64_t *map,
63
+ BlockDriverState **file)
64
{
80
{
65
BDRVGlusterState *s = bs->opaque;
81
Visitor *v;
66
- off_t start, data = 0, hole = 0;
82
Object *obj;
67
- int64_t total_size;
83
@@ -XXX,XX +XXX,XX @@ void user_creatable_add_dict(QDict *qdict, Error **errp)
68
+ off_t data = 0, hole = 0;
69
int ret = -EINVAL;
70
71
if (!s->fd) {
72
return ret;
73
}
84
}
74
85
qdict_del(qdict, "id");
75
- start = sector_num * BDRV_SECTOR_SIZE;
86
76
- total_size = bdrv_getlength(bs);
87
- v = qobject_input_visitor_new(QOBJECT(qdict));
77
- if (total_size < 0) {
88
+ if (keyval) {
78
- return total_size;
89
+ v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
79
- } else if (start >= total_size) {
90
+ } else {
80
- *pnum = 0;
91
+ v = qobject_input_visitor_new(QOBJECT(qdict));
81
- return 0;
92
+ }
82
- } else if (start + nb_sectors * BDRV_SECTOR_SIZE > total_size) {
93
obj = user_creatable_add_type(type, id, qdict, v, errp);
83
- nb_sectors = DIV_ROUND_UP(total_size - start, BDRV_SECTOR_SIZE);
94
visit_free(v);
84
+ if (!want_zero) {
95
object_unref(obj);
85
+ *pnum = bytes;
96
diff --git a/qom/qom-qmp-cmds.c b/qom/qom-qmp-cmds.c
86
+ *map = offset;
97
index XXXXXXX..XXXXXXX 100644
87
+ *file = bs;
98
--- a/qom/qom-qmp-cmds.c
88
+ return BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID;
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);
89
}
102
}
90
103
91
- ret = find_allocation(bs, start, &data, &hole);
104
- user_creatable_add_dict(qdict, errp);
92
+ ret = find_allocation(bs, offset, &data, &hole);
105
+ user_creatable_add_dict(qdict, false, errp);
93
if (ret == -ENXIO) {
94
/* Trailing hole */
95
- *pnum = nb_sectors;
96
+ *pnum = bytes;
97
ret = BDRV_BLOCK_ZERO;
98
} else if (ret < 0) {
99
/* No info available, so pretend there are no holes */
100
- *pnum = nb_sectors;
101
+ *pnum = bytes;
102
ret = BDRV_BLOCK_DATA;
103
- } else if (data == start) {
104
- /* On a data extent, compute sectors to the end of the extent,
105
+ } else if (data == offset) {
106
+ /* On a data extent, compute bytes to the end of the extent,
107
* possibly including a partial sector at EOF. */
108
- *pnum = MIN(nb_sectors, DIV_ROUND_UP(hole - start, BDRV_SECTOR_SIZE));
109
+ *pnum = MIN(bytes, hole - offset);
110
ret = BDRV_BLOCK_DATA;
111
} else {
112
- /* On a hole, compute sectors to the beginning of the next extent. */
113
- assert(hole == start);
114
- *pnum = MIN(nb_sectors, (data - start) / BDRV_SECTOR_SIZE);
115
+ /* On a hole, compute bytes to the beginning of the next extent. */
116
+ assert(hole == offset);
117
+ *pnum = MIN(bytes, data - offset);
118
ret = BDRV_BLOCK_ZERO;
119
}
120
121
+ *map = offset;
122
*file = bs;
123
124
- return ret | BDRV_BLOCK_OFFSET_VALID | start;
125
+ return ret | BDRV_BLOCK_OFFSET_VALID;
126
}
106
}
127
107
128
108
void qmp_object_del(const char *id, Error **errp)
129
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_gluster = {
130
#ifdef CONFIG_GLUSTERFS_ZEROFILL
131
.bdrv_co_pwrite_zeroes = qemu_gluster_co_pwrite_zeroes,
132
#endif
133
- .bdrv_co_get_block_status = qemu_gluster_co_get_block_status,
134
+ .bdrv_co_block_status = qemu_gluster_co_block_status,
135
.create_opts = &qemu_gluster_create_opts,
136
};
137
138
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_gluster_tcp = {
139
#ifdef CONFIG_GLUSTERFS_ZEROFILL
140
.bdrv_co_pwrite_zeroes = qemu_gluster_co_pwrite_zeroes,
141
#endif
142
- .bdrv_co_get_block_status = qemu_gluster_co_get_block_status,
143
+ .bdrv_co_block_status = qemu_gluster_co_block_status,
144
.create_opts = &qemu_gluster_create_opts,
145
};
146
147
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_gluster_unix = {
148
#ifdef CONFIG_GLUSTERFS_ZEROFILL
149
.bdrv_co_pwrite_zeroes = qemu_gluster_co_pwrite_zeroes,
150
#endif
151
- .bdrv_co_get_block_status = qemu_gluster_co_get_block_status,
152
+ .bdrv_co_block_status = qemu_gluster_co_block_status,
153
.create_opts = &qemu_gluster_create_opts,
154
};
155
156
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_gluster_rdma = {
157
#ifdef CONFIG_GLUSTERFS_ZEROFILL
158
.bdrv_co_pwrite_zeroes = qemu_gluster_co_pwrite_zeroes,
159
#endif
160
- .bdrv_co_get_block_status = qemu_gluster_co_get_block_status,
161
+ .bdrv_co_block_status = qemu_gluster_co_block_status,
162
.create_opts = &qemu_gluster_create_opts,
163
};
164
165
--
109
--
166
2.13.6
110
2.25.3
167
111
168
112
diff view generated by jsdifflib
Deleted patch
1
From: Eric Blake <eblake@redhat.com>
2
1
3
We are gradually converting to byte-based interfaces, as they are
4
easier to reason about than sector-based. Convert all uses of
5
the allocmap (no semantic change). Callers that already had bytes
6
available are simpler, and callers that now scale to bytes will be
7
easier to switch to byte-based in the future.
8
9
Signed-off-by: Eric Blake <eblake@redhat.com>
10
Acked-by: Paolo Bonzini <pbonzini@redhat.com>
11
Reviewed-by: Fam Zheng <famz@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
---
14
block/iscsi.c | 90 +++++++++++++++++++++++++++++------------------------------
15
1 file changed, 44 insertions(+), 46 deletions(-)
16
17
diff --git a/block/iscsi.c b/block/iscsi.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/block/iscsi.c
20
+++ b/block/iscsi.c
21
@@ -XXX,XX +XXX,XX @@ static int iscsi_allocmap_init(IscsiLun *iscsilun, int open_flags)
22
}
23
24
static void
25
-iscsi_allocmap_update(IscsiLun *iscsilun, int64_t sector_num,
26
- int nb_sectors, bool allocated, bool valid)
27
+iscsi_allocmap_update(IscsiLun *iscsilun, int64_t offset,
28
+ int64_t bytes, bool allocated, bool valid)
29
{
30
int64_t cl_num_expanded, nb_cls_expanded, cl_num_shrunk, nb_cls_shrunk;
31
- int cluster_sectors = iscsilun->cluster_size >> BDRV_SECTOR_BITS;
32
33
if (iscsilun->allocmap == NULL) {
34
return;
35
}
36
/* expand to entirely contain all affected clusters */
37
- assert(cluster_sectors);
38
- cl_num_expanded = sector_num / cluster_sectors;
39
- nb_cls_expanded = DIV_ROUND_UP(sector_num + nb_sectors,
40
- cluster_sectors) - cl_num_expanded;
41
+ assert(iscsilun->cluster_size);
42
+ cl_num_expanded = offset / iscsilun->cluster_size;
43
+ nb_cls_expanded = DIV_ROUND_UP(offset + bytes,
44
+ iscsilun->cluster_size) - cl_num_expanded;
45
/* shrink to touch only completely contained clusters */
46
- cl_num_shrunk = DIV_ROUND_UP(sector_num, cluster_sectors);
47
- nb_cls_shrunk = (sector_num + nb_sectors) / cluster_sectors
48
- - cl_num_shrunk;
49
+ cl_num_shrunk = DIV_ROUND_UP(offset, iscsilun->cluster_size);
50
+ nb_cls_shrunk = (offset + bytes) / iscsilun->cluster_size - cl_num_shrunk;
51
if (allocated) {
52
bitmap_set(iscsilun->allocmap, cl_num_expanded, nb_cls_expanded);
53
} else {
54
@@ -XXX,XX +XXX,XX @@ iscsi_allocmap_update(IscsiLun *iscsilun, int64_t sector_num,
55
}
56
57
static void
58
-iscsi_allocmap_set_allocated(IscsiLun *iscsilun, int64_t sector_num,
59
- int nb_sectors)
60
+iscsi_allocmap_set_allocated(IscsiLun *iscsilun, int64_t offset,
61
+ int64_t bytes)
62
{
63
- iscsi_allocmap_update(iscsilun, sector_num, nb_sectors, true, true);
64
+ iscsi_allocmap_update(iscsilun, offset, bytes, true, true);
65
}
66
67
static void
68
-iscsi_allocmap_set_unallocated(IscsiLun *iscsilun, int64_t sector_num,
69
- int nb_sectors)
70
+iscsi_allocmap_set_unallocated(IscsiLun *iscsilun, int64_t offset,
71
+ int64_t bytes)
72
{
73
/* Note: if cache.direct=on the fifth argument to iscsi_allocmap_update
74
* is ignored, so this will in effect be an iscsi_allocmap_set_invalid.
75
*/
76
- iscsi_allocmap_update(iscsilun, sector_num, nb_sectors, false, true);
77
+ iscsi_allocmap_update(iscsilun, offset, bytes, false, true);
78
}
79
80
-static void iscsi_allocmap_set_invalid(IscsiLun *iscsilun, int64_t sector_num,
81
- int nb_sectors)
82
+static void iscsi_allocmap_set_invalid(IscsiLun *iscsilun, int64_t offset,
83
+ int64_t bytes)
84
{
85
- iscsi_allocmap_update(iscsilun, sector_num, nb_sectors, false, false);
86
+ iscsi_allocmap_update(iscsilun, offset, bytes, false, false);
87
}
88
89
static void iscsi_allocmap_invalidate(IscsiLun *iscsilun)
90
@@ -XXX,XX +XXX,XX @@ static void iscsi_allocmap_invalidate(IscsiLun *iscsilun)
91
}
92
93
static inline bool
94
-iscsi_allocmap_is_allocated(IscsiLun *iscsilun, int64_t sector_num,
95
- int nb_sectors)
96
+iscsi_allocmap_is_allocated(IscsiLun *iscsilun, int64_t offset,
97
+ int64_t bytes)
98
{
99
unsigned long size;
100
if (iscsilun->allocmap == NULL) {
101
return true;
102
}
103
assert(iscsilun->cluster_size);
104
- size = DIV_ROUND_UP(sector_num + nb_sectors,
105
- iscsilun->cluster_size >> BDRV_SECTOR_BITS);
106
+ size = DIV_ROUND_UP(offset + bytes, iscsilun->cluster_size);
107
return !(find_next_bit(iscsilun->allocmap, size,
108
- sector_num * BDRV_SECTOR_SIZE /
109
- iscsilun->cluster_size) == size);
110
+ offset / iscsilun->cluster_size) == size);
111
}
112
113
static inline bool iscsi_allocmap_is_valid(IscsiLun *iscsilun,
114
- int64_t sector_num, int nb_sectors)
115
+ int64_t offset, int64_t bytes)
116
{
117
unsigned long size;
118
if (iscsilun->allocmap_valid == NULL) {
119
return false;
120
}
121
assert(iscsilun->cluster_size);
122
- size = DIV_ROUND_UP(sector_num + nb_sectors,
123
- iscsilun->cluster_size >> BDRV_SECTOR_BITS);
124
+ size = DIV_ROUND_UP(offset + bytes, iscsilun->cluster_size);
125
return (find_next_zero_bit(iscsilun->allocmap_valid, size,
126
- sector_num * BDRV_SECTOR_SIZE /
127
- iscsilun->cluster_size) == size);
128
+ offset / iscsilun->cluster_size) == size);
129
}
130
131
static int coroutine_fn
132
@@ -XXX,XX +XXX,XX @@ retry:
133
}
134
135
if (iTask.status != SCSI_STATUS_GOOD) {
136
- iscsi_allocmap_set_invalid(iscsilun, sector_num, nb_sectors);
137
+ iscsi_allocmap_set_invalid(iscsilun, sector_num * BDRV_SECTOR_SIZE,
138
+ nb_sectors * BDRV_SECTOR_SIZE);
139
error_report("iSCSI WRITE10/16 failed at lba %" PRIu64 ": %s", lba,
140
iTask.err_str);
141
r = iTask.err_code;
142
goto out_unlock;
143
}
144
145
- iscsi_allocmap_set_allocated(iscsilun, sector_num, nb_sectors);
146
+ iscsi_allocmap_set_allocated(iscsilun, sector_num * BDRV_SECTOR_SIZE,
147
+ nb_sectors * BDRV_SECTOR_SIZE);
148
149
out_unlock:
150
qemu_mutex_unlock(&iscsilun->mutex);
151
@@ -XXX,XX +XXX,XX @@ retry:
152
}
153
154
if (ret & BDRV_BLOCK_ZERO) {
155
- iscsi_allocmap_set_unallocated(iscsilun, sector_num, *pnum);
156
+ iscsi_allocmap_set_unallocated(iscsilun, sector_num * BDRV_SECTOR_SIZE,
157
+ *pnum * BDRV_SECTOR_SIZE);
158
} else {
159
- iscsi_allocmap_set_allocated(iscsilun, sector_num, *pnum);
160
+ iscsi_allocmap_set_allocated(iscsilun, sector_num * BDRV_SECTOR_SIZE,
161
+ *pnum * BDRV_SECTOR_SIZE);
162
}
163
164
if (*pnum > nb_sectors) {
165
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn iscsi_co_readv(BlockDriverState *bs,
166
/* if cache.direct is off and we have a valid entry in our allocation map
167
* we can skip checking the block status and directly return zeroes if
168
* the request falls within an unallocated area */
169
- if (iscsi_allocmap_is_valid(iscsilun, sector_num, nb_sectors) &&
170
- !iscsi_allocmap_is_allocated(iscsilun, sector_num, nb_sectors)) {
171
+ if (iscsi_allocmap_is_valid(iscsilun, sector_num * BDRV_SECTOR_SIZE,
172
+ nb_sectors * BDRV_SECTOR_SIZE) &&
173
+ !iscsi_allocmap_is_allocated(iscsilun, sector_num * BDRV_SECTOR_SIZE,
174
+ nb_sectors * BDRV_SECTOR_SIZE)) {
175
qemu_iovec_memset(iov, 0, 0x00, iov->size);
176
return 0;
177
}
178
179
if (nb_sectors >= ISCSI_CHECKALLOC_THRES &&
180
- !iscsi_allocmap_is_valid(iscsilun, sector_num, nb_sectors) &&
181
- !iscsi_allocmap_is_allocated(iscsilun, sector_num, nb_sectors)) {
182
+ !iscsi_allocmap_is_valid(iscsilun, sector_num * BDRV_SECTOR_SIZE,
183
+ nb_sectors * BDRV_SECTOR_SIZE) &&
184
+ !iscsi_allocmap_is_allocated(iscsilun, sector_num * BDRV_SECTOR_SIZE,
185
+ nb_sectors * BDRV_SECTOR_SIZE)) {
186
int pnum;
187
BlockDriverState *file;
188
/* check the block status from the beginning of the cluster
189
@@ -XXX,XX +XXX,XX @@ retry:
190
goto retry;
191
}
192
193
- iscsi_allocmap_set_invalid(iscsilun, offset >> BDRV_SECTOR_BITS,
194
- bytes >> BDRV_SECTOR_BITS);
195
+ iscsi_allocmap_set_invalid(iscsilun, offset, bytes);
196
197
if (iTask.status == SCSI_STATUS_CHECK_CONDITION) {
198
/* the target might fail with a check condition if it
199
@@ -XXX,XX +XXX,XX @@ retry:
200
}
201
202
if (iTask.status != SCSI_STATUS_GOOD) {
203
- iscsi_allocmap_set_invalid(iscsilun, offset >> BDRV_SECTOR_BITS,
204
- bytes >> BDRV_SECTOR_BITS);
205
+ iscsi_allocmap_set_invalid(iscsilun, offset, bytes);
206
error_report("iSCSI WRITESAME10/16 failed at lba %" PRIu64 ": %s",
207
lba, iTask.err_str);
208
r = iTask.err_code;
209
@@ -XXX,XX +XXX,XX @@ retry:
210
}
211
212
if (flags & BDRV_REQ_MAY_UNMAP) {
213
- iscsi_allocmap_set_invalid(iscsilun, offset >> BDRV_SECTOR_BITS,
214
- bytes >> BDRV_SECTOR_BITS);
215
+ iscsi_allocmap_set_invalid(iscsilun, offset, bytes);
216
} else {
217
- iscsi_allocmap_set_allocated(iscsilun, offset >> BDRV_SECTOR_BITS,
218
- bytes >> BDRV_SECTOR_BITS);
219
+ iscsi_allocmap_set_allocated(iscsilun, offset, bytes);
220
}
221
222
out_unlock:
223
--
224
2.13.6
225
226
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. Update the iscsi driver accordingly. In this case,
5
it is handy to teach iscsi_co_block_status() to handle a NULL map
6
and file parameter, even though the block layer passes non-NULL
7
values, because we also call the function directly. For now, there
8
are no optimizations done based on the want_zero flag.
9
10
We can also make the simplification of asserting that the block
11
layer passed in aligned values.
12
13
Signed-off-by: Eric Blake <eblake@redhat.com>
14
Reviewed-by: Fam Zheng <famz@redhat.com>
15
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
16
---
17
block/iscsi.c | 69 ++++++++++++++++++++++++++++-------------------------------
18
1 file changed, 33 insertions(+), 36 deletions(-)
19
20
diff --git a/block/iscsi.c b/block/iscsi.c
21
index XXXXXXX..XXXXXXX 100644
22
--- a/block/iscsi.c
23
+++ b/block/iscsi.c
24
@@ -XXX,XX +XXX,XX @@ out_unlock:
25
26
27
28
-static int64_t coroutine_fn iscsi_co_get_block_status(BlockDriverState *bs,
29
- int64_t sector_num,
30
- int nb_sectors, int *pnum,
31
- BlockDriverState **file)
32
+static int coroutine_fn iscsi_co_block_status(BlockDriverState *bs,
33
+ bool want_zero, int64_t offset,
34
+ int64_t bytes, int64_t *pnum,
35
+ int64_t *map,
36
+ BlockDriverState **file)
37
{
38
IscsiLun *iscsilun = bs->opaque;
39
struct scsi_get_lba_status *lbas = NULL;
40
struct scsi_lba_status_descriptor *lbasd = NULL;
41
struct IscsiTask iTask;
42
uint64_t lba;
43
- int64_t ret;
44
+ int ret;
45
46
iscsi_co_init_iscsitask(iscsilun, &iTask);
47
48
- if (!is_sector_request_lun_aligned(sector_num, nb_sectors, iscsilun)) {
49
- ret = -EINVAL;
50
- goto out;
51
- }
52
+ assert(QEMU_IS_ALIGNED(offset | bytes, iscsilun->block_size));
53
54
/* default to all sectors allocated */
55
- ret = BDRV_BLOCK_DATA;
56
- ret |= (sector_num << BDRV_SECTOR_BITS) | BDRV_BLOCK_OFFSET_VALID;
57
- *pnum = nb_sectors;
58
+ ret = BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID;
59
+ if (map) {
60
+ *map = offset;
61
+ }
62
+ *pnum = bytes;
63
64
/* LUN does not support logical block provisioning */
65
if (!iscsilun->lbpme) {
66
goto out;
67
}
68
69
- lba = sector_qemu2lun(sector_num, iscsilun);
70
+ lba = offset / iscsilun->block_size;
71
72
qemu_mutex_lock(&iscsilun->mutex);
73
retry:
74
@@ -XXX,XX +XXX,XX @@ retry:
75
76
lbasd = &lbas->descriptors[0];
77
78
- if (sector_qemu2lun(sector_num, iscsilun) != lbasd->lba) {
79
+ if (lba != lbasd->lba) {
80
ret = -EIO;
81
goto out_unlock;
82
}
83
84
- *pnum = sector_lun2qemu(lbasd->num_blocks, iscsilun);
85
+ *pnum = lbasd->num_blocks * iscsilun->block_size;
86
87
if (lbasd->provisioning == SCSI_PROVISIONING_TYPE_DEALLOCATED ||
88
lbasd->provisioning == SCSI_PROVISIONING_TYPE_ANCHORED) {
89
@@ -XXX,XX +XXX,XX @@ retry:
90
}
91
92
if (ret & BDRV_BLOCK_ZERO) {
93
- iscsi_allocmap_set_unallocated(iscsilun, sector_num * BDRV_SECTOR_SIZE,
94
- *pnum * BDRV_SECTOR_SIZE);
95
+ iscsi_allocmap_set_unallocated(iscsilun, offset, *pnum);
96
} else {
97
- iscsi_allocmap_set_allocated(iscsilun, sector_num * BDRV_SECTOR_SIZE,
98
- *pnum * BDRV_SECTOR_SIZE);
99
+ iscsi_allocmap_set_allocated(iscsilun, offset, *pnum);
100
}
101
102
- if (*pnum > nb_sectors) {
103
- *pnum = nb_sectors;
104
+ if (*pnum > bytes) {
105
+ *pnum = bytes;
106
}
107
out_unlock:
108
qemu_mutex_unlock(&iscsilun->mutex);
109
@@ -XXX,XX +XXX,XX @@ out:
110
if (iTask.task != NULL) {
111
scsi_free_scsi_task(iTask.task);
112
}
113
- if (ret > 0 && ret & BDRV_BLOCK_OFFSET_VALID) {
114
+ if (ret > 0 && ret & BDRV_BLOCK_OFFSET_VALID && file) {
115
*file = bs;
116
}
117
return ret;
118
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn iscsi_co_readv(BlockDriverState *bs,
119
nb_sectors * BDRV_SECTOR_SIZE) &&
120
!iscsi_allocmap_is_allocated(iscsilun, sector_num * BDRV_SECTOR_SIZE,
121
nb_sectors * BDRV_SECTOR_SIZE)) {
122
- int pnum;
123
- BlockDriverState *file;
124
+ int64_t pnum;
125
/* check the block status from the beginning of the cluster
126
* containing the start sector */
127
- int cluster_sectors = iscsilun->cluster_size >> BDRV_SECTOR_BITS;
128
- int head;
129
- int64_t ret;
130
-
131
- assert(cluster_sectors);
132
- head = sector_num % cluster_sectors;
133
- ret = iscsi_co_get_block_status(bs, sector_num - head,
134
- BDRV_REQUEST_MAX_SECTORS, &pnum,
135
- &file);
136
+ int64_t head;
137
+ int ret;
138
+
139
+ assert(iscsilun->cluster_size);
140
+ head = (sector_num * BDRV_SECTOR_SIZE) % iscsilun->cluster_size;
141
+ ret = iscsi_co_block_status(bs, true,
142
+ sector_num * BDRV_SECTOR_SIZE - head,
143
+ BDRV_REQUEST_MAX_BYTES, &pnum, NULL, NULL);
144
if (ret < 0) {
145
return ret;
146
}
147
/* if the whole request falls into an unallocated area we can avoid
148
* reading and directly return zeroes instead */
149
- if (ret & BDRV_BLOCK_ZERO && pnum >= nb_sectors + head) {
150
+ if (ret & BDRV_BLOCK_ZERO &&
151
+ pnum >= nb_sectors * BDRV_SECTOR_SIZE + head) {
152
qemu_iovec_memset(iov, 0, 0x00, iov->size);
153
return 0;
154
}
155
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_iscsi = {
156
.bdrv_truncate = iscsi_truncate,
157
.bdrv_refresh_limits = iscsi_refresh_limits,
158
159
- .bdrv_co_get_block_status = iscsi_co_get_block_status,
160
+ .bdrv_co_block_status = iscsi_co_block_status,
161
.bdrv_co_pdiscard = iscsi_co_pdiscard,
162
.bdrv_co_pwrite_zeroes = iscsi_co_pwrite_zeroes,
163
.bdrv_co_readv = iscsi_co_readv,
164
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_iser = {
165
.bdrv_truncate = iscsi_truncate,
166
.bdrv_refresh_limits = iscsi_refresh_limits,
167
168
- .bdrv_co_get_block_status = iscsi_co_get_block_status,
169
+ .bdrv_co_block_status = iscsi_co_block_status,
170
.bdrv_co_pdiscard = iscsi_co_pdiscard,
171
.bdrv_co_pwrite_zeroes = iscsi_co_pwrite_zeroes,
172
.bdrv_co_readv = iscsi_co_readv,
173
--
174
2.13.6
175
176
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. Update the null driver accordingly.
5
6
Signed-off-by: Eric Blake <eblake@redhat.com>
7
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
8
Reviewed-by: Fam Zheng <famz@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
11
block/null.c | 23 ++++++++++++-----------
12
1 file changed, 12 insertions(+), 11 deletions(-)
13
14
diff --git a/block/null.c b/block/null.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/block/null.c
17
+++ b/block/null.c
18
@@ -XXX,XX +XXX,XX @@ static int null_reopen_prepare(BDRVReopenState *reopen_state,
19
return 0;
20
}
21
22
-static int64_t coroutine_fn null_co_get_block_status(BlockDriverState *bs,
23
- int64_t sector_num,
24
- int nb_sectors, int *pnum,
25
- BlockDriverState **file)
26
+static int coroutine_fn null_co_block_status(BlockDriverState *bs,
27
+ bool want_zero, int64_t offset,
28
+ int64_t bytes, int64_t *pnum,
29
+ int64_t *map,
30
+ BlockDriverState **file)
31
{
32
BDRVNullState *s = bs->opaque;
33
- off_t start = sector_num * BDRV_SECTOR_SIZE;
34
+ int ret = BDRV_BLOCK_OFFSET_VALID;
35
36
- *pnum = nb_sectors;
37
+ *pnum = bytes;
38
+ *map = offset;
39
*file = bs;
40
41
if (s->read_zeroes) {
42
- return BDRV_BLOCK_OFFSET_VALID | start | BDRV_BLOCK_ZERO;
43
- } else {
44
- return BDRV_BLOCK_OFFSET_VALID | start;
45
+ ret |= BDRV_BLOCK_ZERO;
46
}
47
+ return ret;
48
}
49
50
static void null_refresh_filename(BlockDriverState *bs, QDict *opts)
51
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_null_co = {
52
.bdrv_co_flush_to_disk = null_co_flush,
53
.bdrv_reopen_prepare = null_reopen_prepare,
54
55
- .bdrv_co_get_block_status = null_co_get_block_status,
56
+ .bdrv_co_block_status = null_co_block_status,
57
58
.bdrv_refresh_filename = null_refresh_filename,
59
};
60
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_null_aio = {
61
.bdrv_aio_flush = null_aio_flush,
62
.bdrv_reopen_prepare = null_reopen_prepare,
63
64
- .bdrv_co_get_block_status = null_co_get_block_status,
65
+ .bdrv_co_block_status = null_co_block_status,
66
67
.bdrv_refresh_filename = null_refresh_filename,
68
};
69
--
70
2.13.6
71
72
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. Update the qcow driver accordingly. There is no
5
intent to optimize based on the want_zero flag for this format.
6
7
Signed-off-by: Eric Blake <eblake@redhat.com>
8
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
9
Reviewed-by: Fam Zheng <famz@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
---
12
block/qcow.c | 27 ++++++++++++++++-----------
13
1 file changed, 16 insertions(+), 11 deletions(-)
14
15
diff --git a/block/qcow.c b/block/qcow.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/block/qcow.c
18
+++ b/block/qcow.c
19
@@ -XXX,XX +XXX,XX @@ static int get_cluster_offset(BlockDriverState *bs,
20
return 1;
21
}
22
23
-static int64_t coroutine_fn qcow_co_get_block_status(BlockDriverState *bs,
24
- int64_t sector_num, int nb_sectors, int *pnum, BlockDriverState **file)
25
+static int coroutine_fn qcow_co_block_status(BlockDriverState *bs,
26
+ bool want_zero,
27
+ int64_t offset, int64_t bytes,
28
+ int64_t *pnum, int64_t *map,
29
+ BlockDriverState **file)
30
{
31
BDRVQcowState *s = bs->opaque;
32
- int index_in_cluster, n, ret;
33
+ int index_in_cluster, ret;
34
+ int64_t n;
35
uint64_t cluster_offset;
36
37
qemu_co_mutex_lock(&s->lock);
38
- ret = get_cluster_offset(bs, sector_num << 9, 0, 0, 0, 0, &cluster_offset);
39
+ ret = get_cluster_offset(bs, offset, 0, 0, 0, 0, &cluster_offset);
40
qemu_co_mutex_unlock(&s->lock);
41
if (ret < 0) {
42
return ret;
43
}
44
- index_in_cluster = sector_num & (s->cluster_sectors - 1);
45
- n = s->cluster_sectors - index_in_cluster;
46
- if (n > nb_sectors)
47
- n = nb_sectors;
48
+ index_in_cluster = offset & (s->cluster_size - 1);
49
+ n = s->cluster_size - index_in_cluster;
50
+ if (n > bytes) {
51
+ n = bytes;
52
+ }
53
*pnum = n;
54
if (!cluster_offset) {
55
return 0;
56
@@ -XXX,XX +XXX,XX @@ static int64_t coroutine_fn qcow_co_get_block_status(BlockDriverState *bs,
57
if ((cluster_offset & QCOW_OFLAG_COMPRESSED) || s->crypto) {
58
return BDRV_BLOCK_DATA;
59
}
60
- cluster_offset |= (index_in_cluster << BDRV_SECTOR_BITS);
61
+ *map = cluster_offset | index_in_cluster;
62
*file = bs->file->bs;
63
- return BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID | cluster_offset;
64
+ return BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID;
65
}
66
67
static int decompress_buffer(uint8_t *out_buf, int out_buf_size,
68
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_qcow = {
69
70
.bdrv_co_readv = qcow_co_readv,
71
.bdrv_co_writev = qcow_co_writev,
72
- .bdrv_co_get_block_status = qcow_co_get_block_status,
73
+ .bdrv_co_block_status = qcow_co_block_status,
74
75
.bdrv_make_empty = qcow_make_empty,
76
.bdrv_co_pwritev_compressed = qcow_co_pwritev_compressed,
77
--
78
2.13.6
79
80
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. Update the qed driver accordingly, taking the opportunity
5
to inline qed_is_allocated_cb() into its lone caller (the callback
6
used to be important, until we switched qed to coroutines). There is
7
no intent to optimize based on the want_zero flag for this format.
8
9
Signed-off-by: Eric Blake <eblake@redhat.com>
10
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
11
Reviewed-by: Fam Zheng <famz@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
---
14
block/qed.c | 76 +++++++++++++++++++------------------------------------------
15
1 file changed, 24 insertions(+), 52 deletions(-)
16
17
diff --git a/block/qed.c b/block/qed.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/block/qed.c
20
+++ b/block/qed.c
21
@@ -XXX,XX +XXX,XX @@ finish:
22
return ret;
23
}
24
25
-typedef struct {
26
- BlockDriverState *bs;
27
- Coroutine *co;
28
- uint64_t pos;
29
- int64_t status;
30
- int *pnum;
31
- BlockDriverState **file;
32
-} QEDIsAllocatedCB;
33
-
34
-/* Called with table_lock held. */
35
-static void qed_is_allocated_cb(void *opaque, int ret, uint64_t offset, size_t len)
36
+static int coroutine_fn bdrv_qed_co_block_status(BlockDriverState *bs,
37
+ bool want_zero,
38
+ int64_t pos, int64_t bytes,
39
+ int64_t *pnum, int64_t *map,
40
+ BlockDriverState **file)
41
{
42
- QEDIsAllocatedCB *cb = opaque;
43
- BDRVQEDState *s = cb->bs->opaque;
44
- *cb->pnum = len / BDRV_SECTOR_SIZE;
45
+ BDRVQEDState *s = bs->opaque;
46
+ size_t len = MIN(bytes, SIZE_MAX);
47
+ int status;
48
+ QEDRequest request = { .l2_table = NULL };
49
+ uint64_t offset;
50
+ int ret;
51
+
52
+ qemu_co_mutex_lock(&s->table_lock);
53
+ ret = qed_find_cluster(s, &request, pos, &len, &offset);
54
+
55
+ *pnum = len;
56
switch (ret) {
57
case QED_CLUSTER_FOUND:
58
- offset |= qed_offset_into_cluster(s, cb->pos);
59
- cb->status = BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID | offset;
60
- *cb->file = cb->bs->file->bs;
61
+ *map = offset | qed_offset_into_cluster(s, pos);
62
+ status = BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID;
63
+ *file = bs->file->bs;
64
break;
65
case QED_CLUSTER_ZERO:
66
- cb->status = BDRV_BLOCK_ZERO;
67
+ status = BDRV_BLOCK_ZERO;
68
break;
69
case QED_CLUSTER_L2:
70
case QED_CLUSTER_L1:
71
- cb->status = 0;
72
+ status = 0;
73
break;
74
default:
75
assert(ret < 0);
76
- cb->status = ret;
77
+ status = ret;
78
break;
79
}
80
81
- if (cb->co) {
82
- aio_co_wake(cb->co);
83
- }
84
-}
85
-
86
-static int64_t coroutine_fn bdrv_qed_co_get_block_status(BlockDriverState *bs,
87
- int64_t sector_num,
88
- int nb_sectors, int *pnum,
89
- BlockDriverState **file)
90
-{
91
- BDRVQEDState *s = bs->opaque;
92
- size_t len = (size_t)nb_sectors * BDRV_SECTOR_SIZE;
93
- QEDIsAllocatedCB cb = {
94
- .bs = bs,
95
- .pos = (uint64_t)sector_num * BDRV_SECTOR_SIZE,
96
- .status = BDRV_BLOCK_OFFSET_MASK,
97
- .pnum = pnum,
98
- .file = file,
99
- };
100
- QEDRequest request = { .l2_table = NULL };
101
- uint64_t offset;
102
- int ret;
103
-
104
- qemu_co_mutex_lock(&s->table_lock);
105
- ret = qed_find_cluster(s, &request, cb.pos, &len, &offset);
106
- qed_is_allocated_cb(&cb, ret, offset, len);
107
-
108
- /* The callback was invoked immediately */
109
- assert(cb.status != BDRV_BLOCK_OFFSET_MASK);
110
-
111
qed_unref_l2_cache_entry(request.l2_table);
112
qemu_co_mutex_unlock(&s->table_lock);
113
114
- return cb.status;
115
+ return status;
116
}
117
118
static BDRVQEDState *acb_to_s(QEDAIOCB *acb)
119
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_qed = {
120
.bdrv_child_perm = bdrv_format_default_perms,
121
.bdrv_create = bdrv_qed_create,
122
.bdrv_has_zero_init = bdrv_has_zero_init_1,
123
- .bdrv_co_get_block_status = bdrv_qed_co_get_block_status,
124
+ .bdrv_co_block_status = bdrv_qed_co_block_status,
125
.bdrv_co_readv = bdrv_qed_co_readv,
126
.bdrv_co_writev = bdrv_qed_co_writev,
127
.bdrv_co_pwrite_zeroes = bdrv_qed_co_pwrite_zeroes,
128
--
129
2.13.6
130
131
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. Update the sheepdog driver accordingly.
5
6
Signed-off-by: Eric Blake <eblake@redhat.com>
7
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
8
Reviewed-by: Fam Zheng <famz@redhat.com>
9
Reviewed-by: Jeff Cody <jcody@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
---
12
block/sheepdog.c | 26 +++++++++++++-------------
13
1 file changed, 13 insertions(+), 13 deletions(-)
14
15
diff --git a/block/sheepdog.c b/block/sheepdog.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/block/sheepdog.c
18
+++ b/block/sheepdog.c
19
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int sd_co_pdiscard(BlockDriverState *bs, int64_t offset,
20
return acb.ret;
21
}
22
23
-static coroutine_fn int64_t
24
-sd_co_get_block_status(BlockDriverState *bs, int64_t sector_num, int nb_sectors,
25
- int *pnum, BlockDriverState **file)
26
+static coroutine_fn int
27
+sd_co_block_status(BlockDriverState *bs, bool want_zero, int64_t offset,
28
+ int64_t bytes, int64_t *pnum, int64_t *map,
29
+ BlockDriverState **file)
30
{
31
BDRVSheepdogState *s = bs->opaque;
32
SheepdogInode *inode = &s->inode;
33
uint32_t object_size = (UINT32_C(1) << inode->block_size_shift);
34
- uint64_t offset = sector_num * BDRV_SECTOR_SIZE;
35
unsigned long start = offset / object_size,
36
- end = DIV_ROUND_UP((sector_num + nb_sectors) *
37
- BDRV_SECTOR_SIZE, object_size);
38
+ end = DIV_ROUND_UP(offset + bytes, object_size);
39
unsigned long idx;
40
- int64_t ret = BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID | offset;
41
+ *map = offset;
42
+ int ret = BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID;
43
44
for (idx = start; idx < end; idx++) {
45
if (inode->data_vdi_id[idx] == 0) {
46
@@ -XXX,XX +XXX,XX @@ sd_co_get_block_status(BlockDriverState *bs, int64_t sector_num, int nb_sectors,
47
}
48
}
49
50
- *pnum = (idx - start) * object_size / BDRV_SECTOR_SIZE;
51
- if (*pnum > nb_sectors) {
52
- *pnum = nb_sectors;
53
+ *pnum = (idx - start) * object_size;
54
+ if (*pnum > bytes) {
55
+ *pnum = bytes;
56
}
57
if (ret > 0 && ret & BDRV_BLOCK_OFFSET_VALID) {
58
*file = bs;
59
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_sheepdog = {
60
.bdrv_co_writev = sd_co_writev,
61
.bdrv_co_flush_to_disk = sd_co_flush_to_disk,
62
.bdrv_co_pdiscard = sd_co_pdiscard,
63
- .bdrv_co_get_block_status = sd_co_get_block_status,
64
+ .bdrv_co_block_status = sd_co_block_status,
65
66
.bdrv_snapshot_create = sd_snapshot_create,
67
.bdrv_snapshot_goto = sd_snapshot_goto,
68
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_sheepdog_tcp = {
69
.bdrv_co_writev = sd_co_writev,
70
.bdrv_co_flush_to_disk = sd_co_flush_to_disk,
71
.bdrv_co_pdiscard = sd_co_pdiscard,
72
- .bdrv_co_get_block_status = sd_co_get_block_status,
73
+ .bdrv_co_block_status = sd_co_block_status,
74
75
.bdrv_snapshot_create = sd_snapshot_create,
76
.bdrv_snapshot_goto = sd_snapshot_goto,
77
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_sheepdog_unix = {
78
.bdrv_co_writev = sd_co_writev,
79
.bdrv_co_flush_to_disk = sd_co_flush_to_disk,
80
.bdrv_co_pdiscard = sd_co_pdiscard,
81
- .bdrv_co_get_block_status = sd_co_get_block_status,
82
+ .bdrv_co_block_status = sd_co_block_status,
83
84
.bdrv_snapshot_create = sd_snapshot_create,
85
.bdrv_snapshot_goto = sd_snapshot_goto,
86
--
87
2.13.6
88
89
diff view generated by jsdifflib
Deleted patch
1
From: Eric Blake <eblake@redhat.com>
2
1
3
Rework the debug define so that we always get -Wformat checking,
4
even when debugging is disabled.
5
6
Signed-off-by: Eric Blake <eblake@redhat.com>
7
Reviewed-by: Stefan Weil <sw@weilnetz.de>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
10
Reviewed-by: Fam Zheng <famz@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
---
13
block/vdi.c | 12 +++++++++---
14
1 file changed, 9 insertions(+), 3 deletions(-)
15
16
diff --git a/block/vdi.c b/block/vdi.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/block/vdi.c
19
+++ b/block/vdi.c
20
@@ -XXX,XX +XXX,XX @@
21
#define DEFAULT_CLUSTER_SIZE (1 * MiB)
22
23
#if defined(CONFIG_VDI_DEBUG)
24
-#define logout(fmt, ...) \
25
- fprintf(stderr, "vdi\t%-24s" fmt, __func__, ##__VA_ARGS__)
26
+#define VDI_DEBUG 1
27
#else
28
-#define logout(fmt, ...) ((void)0)
29
+#define VDI_DEBUG 0
30
#endif
31
32
+#define logout(fmt, ...) \
33
+ do { \
34
+ if (VDI_DEBUG) { \
35
+ fprintf(stderr, "vdi\t%-24s" fmt, __func__, ##__VA_ARGS__); \
36
+ } \
37
+ } while (0)
38
+
39
/* Image signature. */
40
#define VDI_SIGNATURE 0xbeda107f
41
42
--
43
2.13.6
44
45
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. Update the vdi driver accordingly. Note that the
5
TODO is already covered (the block layer guarantees bounds of its
6
requests), and that we can remove the now-unused s->block_sectors.
7
8
Signed-off-by: Eric Blake <eblake@redhat.com>
9
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
10
Reviewed-by: Fam Zheng <famz@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
---
13
block/vdi.c | 33 +++++++++++++--------------------
14
1 file changed, 13 insertions(+), 20 deletions(-)
15
16
diff --git a/block/vdi.c b/block/vdi.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/block/vdi.c
19
+++ b/block/vdi.c
20
@@ -XXX,XX +XXX,XX @@ typedef struct {
21
uint32_t *bmap;
22
/* Size of block (bytes). */
23
uint32_t block_size;
24
- /* Size of block (sectors). */
25
- uint32_t block_sectors;
26
/* First sector of block map. */
27
uint32_t bmap_sector;
28
/* VDI header (converted to host endianness). */
29
@@ -XXX,XX +XXX,XX @@ static int vdi_open(BlockDriverState *bs, QDict *options, int flags,
30
bs->total_sectors = header.disk_size / SECTOR_SIZE;
31
32
s->block_size = header.block_size;
33
- s->block_sectors = header.block_size / SECTOR_SIZE;
34
s->bmap_sector = header.offset_bmap / SECTOR_SIZE;
35
s->header = header;
36
37
@@ -XXX,XX +XXX,XX @@ static int vdi_reopen_prepare(BDRVReopenState *state,
38
return 0;
39
}
40
41
-static int64_t coroutine_fn vdi_co_get_block_status(BlockDriverState *bs,
42
- int64_t sector_num, int nb_sectors, int *pnum, BlockDriverState **file)
43
+static int coroutine_fn vdi_co_block_status(BlockDriverState *bs,
44
+ bool want_zero,
45
+ int64_t offset, int64_t bytes,
46
+ int64_t *pnum, int64_t *map,
47
+ BlockDriverState **file)
48
{
49
- /* TODO: Check for too large sector_num (in bdrv_is_allocated or here). */
50
BDRVVdiState *s = (BDRVVdiState *)bs->opaque;
51
- size_t bmap_index = sector_num / s->block_sectors;
52
- size_t sector_in_block = sector_num % s->block_sectors;
53
- int n_sectors = s->block_sectors - sector_in_block;
54
+ size_t bmap_index = offset / s->block_size;
55
+ size_t index_in_block = offset % s->block_size;
56
uint32_t bmap_entry = le32_to_cpu(s->bmap[bmap_index]);
57
- uint64_t offset;
58
int result;
59
60
- logout("%p, %" PRId64 ", %d, %p\n", bs, sector_num, nb_sectors, pnum);
61
- if (n_sectors > nb_sectors) {
62
- n_sectors = nb_sectors;
63
- }
64
- *pnum = n_sectors;
65
+ logout("%p, %" PRId64 ", %" PRId64 ", %p\n", bs, offset, bytes, pnum);
66
+ *pnum = MIN(s->block_size - index_in_block, bytes);
67
result = VDI_IS_ALLOCATED(bmap_entry);
68
if (!result) {
69
return 0;
70
}
71
72
- offset = s->header.offset_data +
73
- (uint64_t)bmap_entry * s->block_size +
74
- sector_in_block * SECTOR_SIZE;
75
+ *map = s->header.offset_data + (uint64_t)bmap_entry * s->block_size +
76
+ index_in_block;
77
*file = bs->file->bs;
78
- return BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID | offset;
79
+ return BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID;
80
}
81
82
static int coroutine_fn
83
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_vdi = {
84
.bdrv_child_perm = bdrv_format_default_perms,
85
.bdrv_create = vdi_create,
86
.bdrv_has_zero_init = bdrv_has_zero_init_1,
87
- .bdrv_co_get_block_status = vdi_co_get_block_status,
88
+ .bdrv_co_block_status = vdi_co_block_status,
89
.bdrv_make_empty = vdi_make_empty,
90
91
.bdrv_co_preadv = vdi_co_preadv,
92
--
93
2.13.6
94
95
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. Update the vmdk driver accordingly. Drop the
5
now-unused vmdk_find_index_in_cluster().
6
7
Also, fix a pre-existing bug: if find_extent() fails (unlikely,
8
since the block layer did a bounds check), then we must return a
9
failure, rather than 0.
10
11
Signed-off-by: Eric Blake <eblake@redhat.com>
12
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
13
Reviewed-by: Fam Zheng <famz@redhat.com>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
---
16
block/vmdk.c | 38 ++++++++++++++------------------------
17
1 file changed, 14 insertions(+), 24 deletions(-)
18
19
diff --git a/block/vmdk.c b/block/vmdk.c
20
index XXXXXXX..XXXXXXX 100644
21
--- a/block/vmdk.c
22
+++ b/block/vmdk.c
23
@@ -XXX,XX +XXX,XX @@ static inline uint64_t vmdk_find_offset_in_cluster(VmdkExtent *extent,
24
return extent_relative_offset % cluster_size;
25
}
26
27
-static inline uint64_t vmdk_find_index_in_cluster(VmdkExtent *extent,
28
- int64_t sector_num)
29
-{
30
- uint64_t offset;
31
- offset = vmdk_find_offset_in_cluster(extent, sector_num * BDRV_SECTOR_SIZE);
32
- return offset / BDRV_SECTOR_SIZE;
33
-}
34
-
35
-static int64_t coroutine_fn vmdk_co_get_block_status(BlockDriverState *bs,
36
- int64_t sector_num, int nb_sectors, int *pnum, BlockDriverState **file)
37
+static int coroutine_fn vmdk_co_block_status(BlockDriverState *bs,
38
+ bool want_zero,
39
+ int64_t offset, int64_t bytes,
40
+ int64_t *pnum, int64_t *map,
41
+ BlockDriverState **file)
42
{
43
BDRVVmdkState *s = bs->opaque;
44
int64_t index_in_cluster, n, ret;
45
- uint64_t offset;
46
+ uint64_t cluster_offset;
47
VmdkExtent *extent;
48
49
- extent = find_extent(s, sector_num, NULL);
50
+ extent = find_extent(s, offset >> BDRV_SECTOR_BITS, NULL);
51
if (!extent) {
52
- return 0;
53
+ return -EIO;
54
}
55
qemu_co_mutex_lock(&s->lock);
56
- ret = get_cluster_offset(bs, extent, NULL,
57
- sector_num * 512, false, &offset,
58
+ ret = get_cluster_offset(bs, extent, NULL, offset, false, &cluster_offset,
59
0, 0);
60
qemu_co_mutex_unlock(&s->lock);
61
62
- index_in_cluster = vmdk_find_index_in_cluster(extent, sector_num);
63
+ index_in_cluster = vmdk_find_offset_in_cluster(extent, offset);
64
switch (ret) {
65
case VMDK_ERROR:
66
ret = -EIO;
67
@@ -XXX,XX +XXX,XX @@ static int64_t coroutine_fn vmdk_co_get_block_status(BlockDriverState *bs,
68
ret = BDRV_BLOCK_DATA;
69
if (!extent->compressed) {
70
ret |= BDRV_BLOCK_OFFSET_VALID;
71
- ret |= (offset + (index_in_cluster << BDRV_SECTOR_BITS))
72
- & BDRV_BLOCK_OFFSET_MASK;
73
+ *map = cluster_offset + index_in_cluster;
74
}
75
*file = extent->file->bs;
76
break;
77
}
78
79
- n = extent->cluster_sectors - index_in_cluster;
80
- if (n > nb_sectors) {
81
- n = nb_sectors;
82
- }
83
- *pnum = n;
84
+ n = extent->cluster_sectors * BDRV_SECTOR_SIZE - index_in_cluster;
85
+ *pnum = MIN(n, bytes);
86
return ret;
87
}
88
89
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_vmdk = {
90
.bdrv_close = vmdk_close,
91
.bdrv_create = vmdk_create,
92
.bdrv_co_flush_to_disk = vmdk_co_flush,
93
- .bdrv_co_get_block_status = vmdk_co_get_block_status,
94
+ .bdrv_co_block_status = vmdk_co_block_status,
95
.bdrv_get_allocated_file_size = vmdk_get_allocated_file_size,
96
.bdrv_has_zero_init = vmdk_has_zero_init,
97
.bdrv_get_specific_info = vmdk_get_specific_info,
98
--
99
2.13.6
100
101
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. Update the vpc driver accordingly.
5
6
Signed-off-by: Eric Blake <eblake@redhat.com>
7
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
8
Reviewed-by: Fam Zheng <famz@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
11
block/vpc.c | 45 +++++++++++++++++++++++----------------------
12
1 file changed, 23 insertions(+), 22 deletions(-)
13
14
diff --git a/block/vpc.c b/block/vpc.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/block/vpc.c
17
+++ b/block/vpc.c
18
@@ -XXX,XX +XXX,XX @@ fail:
19
return ret;
20
}
21
22
-static int64_t coroutine_fn vpc_co_get_block_status(BlockDriverState *bs,
23
- int64_t sector_num, int nb_sectors, int *pnum, BlockDriverState **file)
24
+static int coroutine_fn vpc_co_block_status(BlockDriverState *bs,
25
+ bool want_zero,
26
+ int64_t offset, int64_t bytes,
27
+ int64_t *pnum, int64_t *map,
28
+ BlockDriverState **file)
29
{
30
BDRVVPCState *s = bs->opaque;
31
VHDFooter *footer = (VHDFooter*) s->footer_buf;
32
- int64_t start, offset;
33
+ int64_t image_offset;
34
bool allocated;
35
- int64_t ret;
36
- int n;
37
+ int ret;
38
+ int64_t n;
39
40
if (be32_to_cpu(footer->type) == VHD_FIXED) {
41
- *pnum = nb_sectors;
42
+ *pnum = bytes;
43
+ *map = offset;
44
*file = bs->file->bs;
45
- return BDRV_BLOCK_RAW | BDRV_BLOCK_OFFSET_VALID |
46
- (sector_num << BDRV_SECTOR_BITS);
47
+ return BDRV_BLOCK_RAW | BDRV_BLOCK_OFFSET_VALID;
48
}
49
50
qemu_co_mutex_lock(&s->lock);
51
52
- offset = get_image_offset(bs, sector_num << BDRV_SECTOR_BITS, false, NULL);
53
- start = offset;
54
- allocated = (offset != -1);
55
+ image_offset = get_image_offset(bs, offset, false, NULL);
56
+ allocated = (image_offset != -1);
57
*pnum = 0;
58
ret = 0;
59
60
do {
61
/* All sectors in a block are contiguous (without using the bitmap) */
62
- n = ROUND_UP(sector_num + 1, s->block_size / BDRV_SECTOR_SIZE)
63
- - sector_num;
64
- n = MIN(n, nb_sectors);
65
+ n = ROUND_UP(offset + 1, s->block_size) - offset;
66
+ n = MIN(n, bytes);
67
68
*pnum += n;
69
- sector_num += n;
70
- nb_sectors -= n;
71
+ offset += n;
72
+ bytes -= n;
73
/* *pnum can't be greater than one block for allocated
74
* sectors since there is always a bitmap in between. */
75
if (allocated) {
76
*file = bs->file->bs;
77
- ret = BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID | start;
78
+ *map = image_offset;
79
+ ret = BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID;
80
break;
81
}
82
- if (nb_sectors == 0) {
83
+ if (bytes == 0) {
84
break;
85
}
86
- offset = get_image_offset(bs, sector_num << BDRV_SECTOR_BITS, false,
87
- NULL);
88
- } while (offset == -1);
89
+ image_offset = get_image_offset(bs, offset, false, NULL);
90
+ } while (image_offset == -1);
91
92
qemu_co_mutex_unlock(&s->lock);
93
return ret;
94
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_vpc = {
95
96
.bdrv_co_preadv = vpc_co_preadv,
97
.bdrv_co_pwritev = vpc_co_pwritev,
98
- .bdrv_co_get_block_status = vpc_co_get_block_status,
99
+ .bdrv_co_block_status = vpc_co_block_status,
100
101
.bdrv_get_info = vpc_get_info,
102
103
--
104
2.13.6
105
106
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. Update the vvfat driver accordingly. Note that we
5
can rely on the block driver having already clamped limits to our
6
block size, and simplify accordingly.
7
8
Signed-off-by: Eric Blake <eblake@redhat.com>
9
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
10
Reviewed-by: Fam Zheng <famz@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
---
13
block/vvfat.c | 16 +++++++---------
14
1 file changed, 7 insertions(+), 9 deletions(-)
15
16
diff --git a/block/vvfat.c b/block/vvfat.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/block/vvfat.c
19
+++ b/block/vvfat.c
20
@@ -XXX,XX +XXX,XX @@ vvfat_co_pwritev(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
21
return ret;
22
}
23
24
-static int64_t coroutine_fn vvfat_co_get_block_status(BlockDriverState *bs,
25
- int64_t sector_num, int nb_sectors, int *n, BlockDriverState **file)
26
+static int coroutine_fn vvfat_co_block_status(BlockDriverState *bs,
27
+ bool want_zero, int64_t offset,
28
+ int64_t bytes, int64_t *n,
29
+ int64_t *map,
30
+ BlockDriverState **file)
31
{
32
- *n = bs->total_sectors - sector_num;
33
- if (*n > nb_sectors) {
34
- *n = nb_sectors;
35
- } else if (*n < 0) {
36
- return 0;
37
- }
38
+ *n = bytes;
39
return BDRV_BLOCK_DATA;
40
}
41
42
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_vvfat = {
43
44
.bdrv_co_preadv = vvfat_co_preadv,
45
.bdrv_co_pwritev = vvfat_co_pwritev,
46
- .bdrv_co_get_block_status = vvfat_co_get_block_status,
47
+ .bdrv_co_block_status = vvfat_co_block_status,
48
};
49
50
static void bdrv_vvfat_init(void)
51
--
52
2.13.6
53
54
diff view generated by jsdifflib
Deleted patch
1
From: Anton Nefedov <anton.nefedov@virtuozzo.com>
2
1
3
This new test case only makes sense for qcow2 while iotest 033 is generic;
4
however it matches the test purpose perfectly and also 033 contains those
5
do_test() tricks to pass the alignment, which won't look nice being
6
duplicated in other tests or moved to the common code.
7
8
Signed-off-by: Anton Nefedov <anton.nefedov@virtuozzo.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
11
tests/qemu-iotests/033 | 29 +++++++++++++++++++++++++++++
12
tests/qemu-iotests/033.out | 13 +++++++++++++
13
2 files changed, 42 insertions(+)
14
15
diff --git a/tests/qemu-iotests/033 b/tests/qemu-iotests/033
16
index XXXXXXX..XXXXXXX 100755
17
--- a/tests/qemu-iotests/033
18
+++ b/tests/qemu-iotests/033
19
@@ -XXX,XX +XXX,XX @@ do_test()
20
    } | $QEMU_IO $IO_EXTRA_ARGS
21
}
22
23
+echo
24
+echo "=== Test aligned and misaligned write zeroes operations ==="
25
+
26
for write_zero_cmd in "write -z" "aio_write -z"; do
27
for align in 512 4k; do
28
    echo
29
@@ -XXX,XX +XXX,XX @@ for align in 512 4k; do
30
done
31
done
32
33
+
34
+# Trigger truncate that would shrink qcow2 L1 table, which is done by
35
+# clearing one entry (8 bytes) with bdrv_co_pwrite_zeroes()
36
+
37
+echo
38
+echo "=== Test misaligned write zeroes via truncate ==="
39
+echo
40
+
41
+# any size will do, but the smaller the size the smaller the required image
42
+CLUSTER_SIZE=$((4 * 1024))
43
+L2_COVERAGE=$(($CLUSTER_SIZE * $CLUSTER_SIZE / 8))
44
+_make_test_img $(($L2_COVERAGE * 2))
45
+
46
+do_test 512 "write -P 1 0 0x200" "$TEST_IMG" | _filter_qemu_io
47
+# next L2 table
48
+do_test 512 "write -P 1 $L2_COVERAGE 0x200" "$TEST_IMG" | _filter_qemu_io
49
+
50
+# only interested in qcow2 here; also other formats might respond with
51
+# "not supported" error message
52
+if [ $IMGFMT = "qcow2" ]; then
53
+ do_test 512 "truncate $L2_COVERAGE" "$TEST_IMG" | _filter_qemu_io
54
+fi
55
+
56
+do_test 512 "read -P 1 0 0x200" "$TEST_IMG" | _filter_qemu_io
57
+
58
# success, all done
59
+echo
60
echo "*** done"
61
rm -f $seq.full
62
status=0
63
diff --git a/tests/qemu-iotests/033.out b/tests/qemu-iotests/033.out
64
index XXXXXXX..XXXXXXX 100644
65
--- a/tests/qemu-iotests/033.out
66
+++ b/tests/qemu-iotests/033.out
67
@@ -XXX,XX +XXX,XX @@
68
QA output created by 033
69
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
70
71
+=== Test aligned and misaligned write zeroes operations ===
72
+
73
== preparing image ==
74
wrote 1024/1024 bytes at offset 512
75
1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
76
@@ -XXX,XX +XXX,XX @@ read 512/512 bytes at offset 512
77
read 3072/3072 bytes at offset 1024
78
3 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
79
80
+
81
+=== Test misaligned write zeroes via truncate ===
82
+
83
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=4194304
84
+wrote 512/512 bytes at offset 0
85
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
86
+wrote 512/512 bytes at offset 2097152
87
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
88
+read 512/512 bytes at offset 0
89
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
90
+
91
*** done
92
--
93
2.13.6
94
95
diff view generated by jsdifflib
Deleted patch
1
From: Alberto Garcia <berto@igalia.com>
2
1
3
This patch updates docs/qcow2-cache.txt explaining how to use the new
4
l2-cache-entry-size parameter.
5
6
Here's a more detailed technical description of this feature:
7
8
https://lists.gnu.org/archive/html/qemu-block/2017-09/msg00635.html
9
10
And here are some performance numbers:
11
12
https://lists.gnu.org/archive/html/qemu-block/2017-12/msg00507.html
13
14
Signed-off-by: Alberto Garcia <berto@igalia.com>
15
Reviewed-by: Eric Blake <eblake@redhat.com>
16
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
17
---
18
docs/qcow2-cache.txt | 46 +++++++++++++++++++++++++++++++++++++++++++---
19
1 file changed, 43 insertions(+), 3 deletions(-)
20
21
diff --git a/docs/qcow2-cache.txt b/docs/qcow2-cache.txt
22
index XXXXXXX..XXXXXXX 100644
23
--- a/docs/qcow2-cache.txt
24
+++ b/docs/qcow2-cache.txt
25
@@ -XXX,XX +XXX,XX @@
26
qcow2 L2/refcount cache configuration
27
=====================================
28
-Copyright (C) 2015 Igalia, S.L.
29
+Copyright (C) 2015, 2018 Igalia, S.L.
30
Author: Alberto Garcia <berto@igalia.com>
31
32
This work is licensed under the terms of the GNU GPL, version 2 or
33
@@ -XXX,XX +XXX,XX @@ There are three options available, and all of them take bytes:
34
35
There are two things that need to be taken into account:
36
37
- - Both caches must have a size that is a multiple of the cluster
38
- size.
39
+ - Both caches must have a size that is a multiple of the cluster size
40
+ (or the cache entry size: see "Using smaller cache sizes" below).
41
42
- If you only set one of the options above, QEMU will automatically
43
adjust the others so that the L2 cache is 4 times bigger than the
44
@@ -XXX,XX +XXX,XX @@ much less often than the L2 cache, so it's perfectly reasonable to
45
keep it small.
46
47
48
+Using smaller cache entries
49
+---------------------------
50
+The qcow2 L2 cache stores complete tables by default. This means that
51
+if QEMU needs an entry from an L2 table then the whole table is read
52
+from disk and is kept in the cache. If the cache is full then a
53
+complete table needs to be evicted first.
54
+
55
+This can be inefficient with large cluster sizes since it results in
56
+more disk I/O and wastes more cache memory.
57
+
58
+Since QEMU 2.12 you can change the size of the L2 cache entry and make
59
+it smaller than the cluster size. This can be configured using the
60
+"l2-cache-entry-size" parameter:
61
+
62
+ -drive file=hd.qcow2,l2-cache-size=2097152,l2-cache-entry-size=4096
63
+
64
+Some things to take into account:
65
+
66
+ - The L2 cache entry size has the same restrictions as the cluster
67
+ size (power of two, at least 512 bytes).
68
+
69
+ - Smaller entry sizes generally improve the cache efficiency and make
70
+ disk I/O faster. This is particularly true with solid state drives
71
+ so it's a good idea to reduce the entry size in those cases. With
72
+ rotating hard drives the situation is a bit more complicated so you
73
+ should test it first and stay with the default size if unsure.
74
+
75
+ - Try different entry sizes to see which one gives faster performance
76
+ in your case. The block size of the host filesystem is generally a
77
+ good default (usually 4096 bytes in the case of ext4).
78
+
79
+ - Only the L2 cache can be configured this way. The refcount cache
80
+ always uses the cluster size as the entry size.
81
+
82
+ - If the L2 cache is big enough to hold all of the image's L2 tables
83
+ (as explained in the "Choosing the right cache sizes" section
84
+ earlier in this document) then none of this is necessary and you
85
+ can omit the "l2-cache-entry-size" parameter altogether.
86
+
87
+
88
Reducing the memory usage
89
-------------------------
90
It is possible to clean unused cache entries in order to reduce the
91
--
92
2.13.6
93
94
diff view generated by jsdifflib
Deleted patch
1
From: Stefan Hajnoczi <stefanha@redhat.com>
2
1
3
The name aio_context_in_iothread() is misleading because it also returns
4
true when called on the main AioContext from the main loop thread, which
5
is not an IOThread.
6
7
This patch renames it to in_aio_context_home_thread() and expands the
8
doc comment to make the semantics clearer.
9
10
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
11
Reviewed-by: Eric Blake <eblake@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
---
14
include/block/aio.h | 7 +++++--
15
include/block/block.h | 2 +-
16
2 files changed, 6 insertions(+), 3 deletions(-)
17
18
diff --git a/include/block/aio.h b/include/block/aio.h
19
index XXXXXXX..XXXXXXX 100644
20
--- a/include/block/aio.h
21
+++ b/include/block/aio.h
22
@@ -XXX,XX +XXX,XX @@ void aio_co_enter(AioContext *ctx, struct Coroutine *co);
23
AioContext *qemu_get_current_aio_context(void);
24
25
/**
26
+ * in_aio_context_home_thread:
27
* @ctx: the aio context
28
*
29
- * Return whether we are running in the I/O thread that manages @ctx.
30
+ * Return whether we are running in the thread that normally runs @ctx. Note
31
+ * that acquiring/releasing ctx does not affect the outcome, each AioContext
32
+ * still only has one home thread that is responsible for running it.
33
*/
34
-static inline bool aio_context_in_iothread(AioContext *ctx)
35
+static inline bool in_aio_context_home_thread(AioContext *ctx)
36
{
37
return ctx == qemu_get_current_aio_context();
38
}
39
diff --git a/include/block/block.h b/include/block/block.h
40
index XXXXXXX..XXXXXXX 100644
41
--- a/include/block/block.h
42
+++ b/include/block/block.h
43
@@ -XXX,XX +XXX,XX @@ void bdrv_drain_all(void);
44
bool busy_ = true; \
45
BlockDriverState *bs_ = (bs); \
46
AioContext *ctx_ = bdrv_get_aio_context(bs_); \
47
- if (aio_context_in_iothread(ctx_)) { \
48
+ if (in_aio_context_home_thread(ctx_)) { \
49
while ((cond) || busy_) { \
50
busy_ = aio_poll(ctx_, (cond)); \
51
waited_ |= !!(cond) | busy_; \
52
--
53
2.13.6
54
55
diff view generated by jsdifflib
Deleted patch
1
From: Stefan Hajnoczi <stefanha@redhat.com>
2
1
3
BlockBackend currently relies on BlockDriverState->in_flight to track
4
requests for blk_drain(). There is a corner case where
5
BlockDriverState->in_flight cannot be used though: blk->root can be NULL
6
when there is no medium. This results in a segfault when the NULL
7
pointer is dereferenced.
8
9
Introduce a BlockBackend->in_flight counter for aio requests so it works
10
even when blk->root == NULL.
11
12
Based on a patch by Kevin Wolf <kwolf@redhat.com>.
13
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
16
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
17
---
18
block.c | 2 +-
19
block/block-backend.c | 60 +++++++++++++++++++++++++++++++++++++++++++++------
20
2 files changed, 54 insertions(+), 8 deletions(-)
21
22
diff --git a/block.c b/block.c
23
index XXXXXXX..XXXXXXX 100644
24
--- a/block.c
25
+++ b/block.c
26
@@ -XXX,XX +XXX,XX @@ out:
27
28
AioContext *bdrv_get_aio_context(BlockDriverState *bs)
29
{
30
- return bs->aio_context;
31
+ return bs ? bs->aio_context : qemu_get_aio_context();
32
}
33
34
AioWait *bdrv_get_aio_wait(BlockDriverState *bs)
35
diff --git a/block/block-backend.c b/block/block-backend.c
36
index XXXXXXX..XXXXXXX 100644
37
--- a/block/block-backend.c
38
+++ b/block/block-backend.c
39
@@ -XXX,XX +XXX,XX @@ struct BlockBackend {
40
int quiesce_counter;
41
VMChangeStateEntry *vmsh;
42
bool force_allow_inactivate;
43
+
44
+ /* Number of in-flight aio requests. BlockDriverState also counts
45
+ * in-flight requests but aio requests can exist even when blk->root is
46
+ * NULL, so we cannot rely on its counter for that case.
47
+ * Accessed with atomic ops.
48
+ */
49
+ unsigned int in_flight;
50
+ AioWait wait;
51
};
52
53
typedef struct BlockBackendAIOCB {
54
@@ -XXX,XX +XXX,XX @@ int blk_make_zero(BlockBackend *blk, BdrvRequestFlags flags)
55
return bdrv_make_zero(blk->root, flags);
56
}
57
58
+static void blk_inc_in_flight(BlockBackend *blk)
59
+{
60
+ atomic_inc(&blk->in_flight);
61
+}
62
+
63
+static void blk_dec_in_flight(BlockBackend *blk)
64
+{
65
+ atomic_dec(&blk->in_flight);
66
+ aio_wait_kick(&blk->wait);
67
+}
68
+
69
static void error_callback_bh(void *opaque)
70
{
71
struct BlockBackendAIOCB *acb = opaque;
72
73
- bdrv_dec_in_flight(acb->common.bs);
74
+ blk_dec_in_flight(acb->blk);
75
acb->common.cb(acb->common.opaque, acb->ret);
76
qemu_aio_unref(acb);
77
}
78
@@ -XXX,XX +XXX,XX @@ BlockAIOCB *blk_abort_aio_request(BlockBackend *blk,
79
{
80
struct BlockBackendAIOCB *acb;
81
82
- bdrv_inc_in_flight(blk_bs(blk));
83
+ blk_inc_in_flight(blk);
84
acb = blk_aio_get(&block_backend_aiocb_info, blk, cb, opaque);
85
acb->blk = blk;
86
acb->ret = ret;
87
@@ -XXX,XX +XXX,XX @@ static const AIOCBInfo blk_aio_em_aiocb_info = {
88
static void blk_aio_complete(BlkAioEmAIOCB *acb)
89
{
90
if (acb->has_returned) {
91
- bdrv_dec_in_flight(acb->common.bs);
92
+ blk_dec_in_flight(acb->rwco.blk);
93
acb->common.cb(acb->common.opaque, acb->rwco.ret);
94
qemu_aio_unref(acb);
95
}
96
@@ -XXX,XX +XXX,XX @@ static BlockAIOCB *blk_aio_prwv(BlockBackend *blk, int64_t offset, int bytes,
97
BlkAioEmAIOCB *acb;
98
Coroutine *co;
99
100
- bdrv_inc_in_flight(blk_bs(blk));
101
+ blk_inc_in_flight(blk);
102
acb = blk_aio_get(&blk_aio_em_aiocb_info, blk, cb, opaque);
103
acb->rwco = (BlkRwCo) {
104
.blk = blk,
105
@@ -XXX,XX +XXX,XX @@ int blk_flush(BlockBackend *blk)
106
107
void blk_drain(BlockBackend *blk)
108
{
109
- if (blk_bs(blk)) {
110
- bdrv_drain(blk_bs(blk));
111
+ BlockDriverState *bs = blk_bs(blk);
112
+
113
+ if (bs) {
114
+ bdrv_drained_begin(bs);
115
+ }
116
+
117
+ /* We may have -ENOMEDIUM completions in flight */
118
+ AIO_WAIT_WHILE(&blk->wait,
119
+ blk_get_aio_context(blk),
120
+ atomic_mb_read(&blk->in_flight) > 0);
121
+
122
+ if (bs) {
123
+ bdrv_drained_end(bs);
124
}
125
}
126
127
void blk_drain_all(void)
128
{
129
- bdrv_drain_all();
130
+ BlockBackend *blk = NULL;
131
+
132
+ bdrv_drain_all_begin();
133
+
134
+ while ((blk = blk_all_next(blk)) != NULL) {
135
+ AioContext *ctx = blk_get_aio_context(blk);
136
+
137
+ aio_context_acquire(ctx);
138
+
139
+ /* We may have -ENOMEDIUM completions in flight */
140
+ AIO_WAIT_WHILE(&blk->wait, ctx,
141
+ atomic_mb_read(&blk->in_flight) > 0);
142
+
143
+ aio_context_release(ctx);
144
+ }
145
+
146
+ bdrv_drain_all_end();
147
}
148
149
void blk_set_on_error(BlockBackend *blk, BlockdevOnError on_read_error,
150
--
151
2.13.6
152
153
diff view generated by jsdifflib
Deleted patch
1
From: Stefan Hajnoczi <stefanha@redhat.com>
2
1
3
This reverts commit 4da97120d51a4383aa96d741a2b837f8c4bbcd0b.
4
5
blk_aio_flush() now handles the blk->root == NULL case, so we no longer
6
need this workaround.
7
8
Cc: John Snow <jsnow@redhat.com>
9
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
10
Reviewed-by: Eric Blake <eblake@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
---
13
hw/ide/core.c | 10 +---------
14
1 file changed, 1 insertion(+), 9 deletions(-)
15
16
diff --git a/hw/ide/core.c b/hw/ide/core.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/ide/core.c
19
+++ b/hw/ide/core.c
20
@@ -XXX,XX +XXX,XX @@ static void ide_flush_cache(IDEState *s)
21
s->status |= BUSY_STAT;
22
ide_set_retry(s);
23
block_acct_start(blk_get_stats(s->blk), &s->acct, 0, BLOCK_ACCT_FLUSH);
24
-
25
- if (blk_bs(s->blk)) {
26
- s->pio_aiocb = blk_aio_flush(s->blk, ide_flush_cb, s);
27
- } else {
28
- /* XXX blk_aio_flush() crashes when blk_bs(blk) is NULL, remove this
29
- * temporary workaround when blk_aio_*() functions handle NULL blk_bs.
30
- */
31
- ide_flush_cb(s, 0);
32
- }
33
+ s->pio_aiocb = blk_aio_flush(s->blk, ide_flush_cb, s);
34
}
35
36
static void ide_cfata_metadata_inquiry(IDEState *s)
37
--
38
2.13.6
39
40
diff view generated by jsdifflib
Deleted patch
1
From: Max Reitz <mreitz@redhat.com>
2
1
3
The issue:
4
5
$ qemu-img resize -f qcow2 foo.qcow2
6
qemu-img: Expecting one image file name
7
Try 'qemu-img --help' for more information
8
9
So we gave an image file name, but we omitted the length. qemu-img
10
thinks the last argument is always the size and removes it immediately
11
from argv (by decrementing argc), and tries to verify that it is a valid
12
size only at a later point.
13
14
So we do not actually know whether that last argument we called "size"
15
is indeed a size or whether the user instead forgot to specify that size
16
but did give a file name.
17
18
Therefore, the error message should be more general.
19
20
Bug: https://bugzilla.redhat.com/show_bug.cgi?id=1523458
21
Signed-off-by: Max Reitz <mreitz@redhat.com>
22
Message-id: 20180205162745.23650-1-mreitz@redhat.com
23
Reviewed-by: John Snow <jsnow@redhat.com>
24
Reviewed-by: Eric Blake <eblake@redhat.com>
25
Signed-off-by: Max Reitz <mreitz@redhat.com>
26
---
27
qemu-img.c | 2 +-
28
1 file changed, 1 insertion(+), 1 deletion(-)
29
30
diff --git a/qemu-img.c b/qemu-img.c
31
index XXXXXXX..XXXXXXX 100644
32
--- a/qemu-img.c
33
+++ b/qemu-img.c
34
@@ -XXX,XX +XXX,XX @@ static int img_resize(int argc, char **argv)
35
}
36
}
37
if (optind != argc - 1) {
38
- error_exit("Expecting one image file name");
39
+ error_exit("Expecting image file name and size");
40
}
41
filename = argv[optind++];
42
43
--
44
2.13.6
45
46
diff view generated by jsdifflib
Deleted patch
1
From: Max Reitz <mreitz@redhat.com>
2
1
3
If we ever want to offer even rudimentary truncation functionality for
4
ssh, we should put the respective code into a reusable function.
5
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
Message-id: 20180214204915.7980-2-mreitz@redhat.com
8
Reviewed-by: Eric Blake <eblake@redhat.com>
9
Reviewed-by: Richard W.M. Jones <rjones@redhat.com>
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
---
12
block/ssh.c | 30 ++++++++++++++++++++++--------
13
1 file changed, 22 insertions(+), 8 deletions(-)
14
15
diff --git a/block/ssh.c b/block/ssh.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/block/ssh.c
18
+++ b/block/ssh.c
19
@@ -XXX,XX +XXX,XX @@ static int ssh_file_open(BlockDriverState *bs, QDict *options, int bdrv_flags,
20
return ret;
21
}
22
23
+static int ssh_grow_file(BDRVSSHState *s, int64_t offset, Error **errp)
24
+{
25
+ ssize_t ret;
26
+ char c[1] = { '\0' };
27
+
28
+ /* offset must be strictly greater than the current size so we do
29
+ * not overwrite anything */
30
+ assert(offset > 0 && offset > s->attrs.filesize);
31
+
32
+ libssh2_sftp_seek64(s->sftp_handle, offset - 1);
33
+ ret = libssh2_sftp_write(s->sftp_handle, c, 1);
34
+ if (ret < 0) {
35
+ sftp_error_setg(errp, s, "Failed to grow file");
36
+ return -EIO;
37
+ }
38
+
39
+ s->attrs.filesize = offset;
40
+ return 0;
41
+}
42
+
43
static QemuOptsList ssh_create_opts = {
44
.name = "ssh-create-opts",
45
.head = QTAILQ_HEAD_INITIALIZER(ssh_create_opts.head),
46
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn ssh_co_create_opts(const char *filename, QemuOpts *opts,
47
int64_t total_size = 0;
48
QDict *uri_options = NULL;
49
BDRVSSHState s;
50
- ssize_t r2;
51
- char c[1] = { '\0' };
52
53
ssh_state_init(&s);
54
55
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn ssh_co_create_opts(const char *filename, QemuOpts *opts,
56
}
57
58
if (total_size > 0) {
59
- libssh2_sftp_seek64(s.sftp_handle, total_size-1);
60
- r2 = libssh2_sftp_write(s.sftp_handle, c, 1);
61
- if (r2 < 0) {
62
- sftp_error_setg(errp, &s, "truncate failed");
63
- ret = -EINVAL;
64
+ ret = ssh_grow_file(&s, total_size, errp);
65
+ if (ret < 0) {
66
goto out;
67
}
68
- s.attrs.filesize = total_size;
69
}
70
71
ret = 0;
72
--
73
2.13.6
74
75
diff view generated by jsdifflib
Deleted patch
1
From: Max Reitz <mreitz@redhat.com>
2
1
3
At runtime (that is, during a future ssh_truncate()), the SSH session is
4
non-blocking. However, ssh_truncate() (or rather, bdrv_truncate() in
5
general) is not a coroutine, so this resize operation needs to block.
6
7
For ssh_create(), that is fine, too; the session is never set to
8
non-blocking anyway.
9
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
Message-id: 20180214204915.7980-3-mreitz@redhat.com
12
Reviewed-by: Eric Blake <eblake@redhat.com>
13
Reviewed-by: Richard W.M. Jones <rjones@redhat.com>
14
Signed-off-by: Max Reitz <mreitz@redhat.com>
15
---
16
block/ssh.c | 7 +++++++
17
1 file changed, 7 insertions(+)
18
19
diff --git a/block/ssh.c b/block/ssh.c
20
index XXXXXXX..XXXXXXX 100644
21
--- a/block/ssh.c
22
+++ b/block/ssh.c
23
@@ -XXX,XX +XXX,XX @@ static int ssh_file_open(BlockDriverState *bs, QDict *options, int bdrv_flags,
24
return ret;
25
}
26
27
+/* Note: This is a blocking operation */
28
static int ssh_grow_file(BDRVSSHState *s, int64_t offset, Error **errp)
29
{
30
ssize_t ret;
31
char c[1] = { '\0' };
32
+ int was_blocking = libssh2_session_get_blocking(s->session);
33
34
/* offset must be strictly greater than the current size so we do
35
* not overwrite anything */
36
assert(offset > 0 && offset > s->attrs.filesize);
37
38
+ libssh2_session_set_blocking(s->session, 1);
39
+
40
libssh2_sftp_seek64(s->sftp_handle, offset - 1);
41
ret = libssh2_sftp_write(s->sftp_handle, c, 1);
42
+
43
+ libssh2_session_set_blocking(s->session, was_blocking);
44
+
45
if (ret < 0) {
46
sftp_error_setg(errp, s, "Failed to grow file");
47
return -EIO;
48
--
49
2.13.6
50
51
diff view generated by jsdifflib
Deleted patch
1
From: Max Reitz <mreitz@redhat.com>
2
1
3
libssh2 does not seem to offer real truncation support, so we can only
4
grow files -- but that is better than nothing.
5
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
Message-id: 20180214204915.7980-4-mreitz@redhat.com
8
Reviewed-by: Eric Blake <eblake@redhat.com>
9
Reviewed-by: Richard W.M. Jones <rjones@redhat.com>
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
---
12
block/ssh.c | 24 ++++++++++++++++++++++++
13
1 file changed, 24 insertions(+)
14
15
diff --git a/block/ssh.c b/block/ssh.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/block/ssh.c
18
+++ b/block/ssh.c
19
@@ -XXX,XX +XXX,XX @@ static int64_t ssh_getlength(BlockDriverState *bs)
20
return length;
21
}
22
23
+static int ssh_truncate(BlockDriverState *bs, int64_t offset,
24
+ PreallocMode prealloc, Error **errp)
25
+{
26
+ BDRVSSHState *s = bs->opaque;
27
+
28
+ if (prealloc != PREALLOC_MODE_OFF) {
29
+ error_setg(errp, "Unsupported preallocation mode '%s'",
30
+ PreallocMode_str(prealloc));
31
+ return -ENOTSUP;
32
+ }
33
+
34
+ if (offset < s->attrs.filesize) {
35
+ error_setg(errp, "ssh driver does not support shrinking files");
36
+ return -ENOTSUP;
37
+ }
38
+
39
+ if (offset == s->attrs.filesize) {
40
+ return 0;
41
+ }
42
+
43
+ return ssh_grow_file(s, offset, errp);
44
+}
45
+
46
static BlockDriver bdrv_ssh = {
47
.format_name = "ssh",
48
.protocol_name = "ssh",
49
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_ssh = {
50
.bdrv_co_readv = ssh_co_readv,
51
.bdrv_co_writev = ssh_co_writev,
52
.bdrv_getlength = ssh_getlength,
53
+ .bdrv_truncate = ssh_truncate,
54
.bdrv_co_flush_to_disk = ssh_co_flush,
55
.create_opts = &ssh_create_opts,
56
};
57
--
58
2.13.6
59
60
diff view generated by jsdifflib