1
The following changes since commit b34181056c04e05db6c632063012beaee7006a37:
1
The following changes since commit dfaecc04c46d298e9ee81bd0ca96d8754f1c27ed:
2
2
3
Merge remote-tracking branch 'remotes/rth/tags/pull-sh4-20180709' into staging (2018-07-09 22:44:22 +0100)
3
Merge tag 'pull-riscv-to-apply-20250407-1' of https://github.com/alistair23/qemu into staging (2025-04-07 09:18:33 -0400)
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
https://repo.or.cz/qemu/kevin.git tags/for-upstream
8
8
9
for you to fetch changes up to cd47d792d7a27a57f4b621e2ff1ed8f4e83de1e9:
9
for you to fetch changes up to f8222bfba3409a3ce09c191941127a8cf2c7e623:
10
10
11
block: Use common write req handling in truncate (2018-07-10 16:46:22 +0200)
11
test-bdrv-drain: Fix data races (2025-04-08 15:00:01 +0200)
12
12
13
----------------------------------------------------------------
13
----------------------------------------------------------------
14
Block layer patches:
14
Block layer patches
15
15
16
- Copy offloading fixes for when the copy increases the image size
16
- scsi-disk: Apply error policy for host_status errors again
17
- Temporary revert of the removal of deprecated -drive options
17
- qcow2: Fix qemu-img info crash with missing crypto header
18
- Fix request serialisation in the image fleecing scenario
18
- qemu-img bench: Fix division by zero for zero-sized images
19
- Fix copy-on-read crash with unaligned image size
19
- test-bdrv-drain: Fix data races
20
- Fix another drain crash
21
20
22
----------------------------------------------------------------
21
----------------------------------------------------------------
23
Ari Sundholm (2):
22
Denis Rastyogin (1):
24
qapi/block-core.json: Add missing documentation for blklogwrites log-append option
23
qemu-img: fix division by zero in bench_cb() for zero-sized images
25
block/blklogwrites: Make sure the log sector size is not too small
26
24
27
Cornelia Huck (4):
25
Kevin Wolf (2):
28
Revert "block: Remove dead deprecation warning code"
26
qcow2: Don't crash qemu-img info with missing crypto header
29
Revert "block: Remove deprecated -drive option serial"
27
scsi-disk: Apply error policy for host_status errors again
30
Revert "block: Remove deprecated -drive option addr"
31
Revert "block: Remove deprecated -drive geometry options"
32
28
33
Fam Zheng (11):
29
Vitalii Mordan (1):
34
iotests: 222: Don't run with luks
30
test-bdrv-drain: Fix data races
35
block: Prefix file driver trace points with "file_"
36
block: Add copy offloading trace points
37
block: Use BdrvChild to discard
38
block: Use uint64_t for BdrvTrackedRequest byte fields
39
block: Extract common write req handling
40
block: Fix handling of image enlarging write
41
block: Use common req handling for discard
42
block: Use common req handling in copy offloading
43
block: Fix bdrv_co_truncate overlap check
44
block: Use common write req handling in truncate
45
31
46
Kevin Wolf (3):
32
include/qemu/job.h | 3 ++
47
block: Poll after drain on attaching a node
33
block/qcow2.c | 4 +-
48
test-bdrv-drain: Test bdrv_append() to drained node
34
hw/scsi/scsi-disk.c | 39 +++++++++-----
49
block: Fix copy-on-read crash with partial final cluster
35
job.c | 6 +++
50
36
qemu-img.c | 6 ++-
51
Vladimir Sementsov-Ogievskiy (4):
37
tests/unit/test-bdrv-drain.c | 32 +++++++-----
52
block/io: fix copy_range
38
tests/qemu-iotests/tests/qcow2-encryption | 75 +++++++++++++++++++++++++++
53
block: split flags in copy_range
39
tests/qemu-iotests/tests/qcow2-encryption.out | 32 ++++++++++++
54
block: add BDRV_REQ_SERIALISING flag
40
8 files changed, 167 insertions(+), 30 deletions(-)
55
block/backup: fix fleecing scheme: use serialized writes
41
create mode 100755 tests/qemu-iotests/tests/qcow2-encryption
56
42
create mode 100644 tests/qemu-iotests/tests/qcow2-encryption.out
57
qapi/block-core.json | 2 +
58
include/block/block.h | 41 +++++-
59
include/block/block_int.h | 21 ++-
60
include/hw/block/block.h | 1 +
61
include/sysemu/block-backend.h | 3 +-
62
include/sysemu/blockdev.h | 3 +
63
block.c | 2 +-
64
block/backup.c | 20 ++-
65
block/blkdebug.c | 2 +-
66
block/blklogwrites.c | 7 +-
67
block/blkreplay.c | 2 +-
68
block/block-backend.c | 8 +-
69
block/copy-on-read.c | 2 +-
70
block/file-posix.c | 25 ++--
71
block/file-win32.c | 2 +-
72
block/io.c | 318 ++++++++++++++++++++++++++++-------------
73
block/iscsi.c | 12 +-
74
block/mirror.c | 2 +-
75
block/qcow2-refcount.c | 2 +-
76
block/qcow2.c | 20 +--
77
block/raw-format.c | 26 ++--
78
block/throttle.c | 2 +-
79
blockdev.c | 110 ++++++++++++++
80
device-hotplug.c | 4 +
81
hw/block/block.c | 27 ++++
82
hw/block/nvme.c | 1 +
83
hw/block/virtio-blk.c | 1 +
84
hw/ide/qdev.c | 1 +
85
hw/scsi/scsi-disk.c | 1 +
86
hw/usb/dev-storage.c | 1 +
87
qemu-img.c | 2 +-
88
tests/ahci-test.c | 6 +-
89
tests/hd-geo-test.c | 37 ++++-
90
tests/ide-test.c | 8 +-
91
tests/test-bdrv-drain.c | 43 ++++++
92
block/trace-events | 10 +-
93
hmp-commands.hx | 1 +
94
qemu-doc.texi | 15 ++
95
qemu-options.hx | 14 +-
96
tests/qemu-iotests/197 | 9 ++
97
tests/qemu-iotests/197.out | 8 ++
98
tests/qemu-iotests/222 | 2 +
99
42 files changed, 647 insertions(+), 177 deletions(-)
100
diff view generated by jsdifflib
Deleted patch
1
Commit dcf94a23b1 ('block: Don't poll in parent drain callbacks')
2
removed polling in bdrv_child_cb_drained_begin() on the grounds that the
3
original bdrv_drain() already will poll and BdrvChildRole.drained_begin
4
calls must not cause graph changes (and therefore must not call
5
aio_poll() or the recursion through the graph will break.
6
1
7
This reasoning is correct for calls through bdrv_do_drained_begin().
8
However, BdrvChildRole.drained_begin is also called when a node that is
9
already in a drained section (i.e. bdrv_do_drained_begin() has already
10
returned and therefore can't poll any more) is attached to a new parent.
11
In this case, we must explicitly poll to have all requests completed
12
before the drained new child can be attached to the parent.
13
14
In bdrv_replace_child_noperm(), we know that we're not inside the
15
recursion of bdrv_do_drained_begin() because graph changes are not
16
allowed there, and bdrv_replace_child_noperm() is a graph change. The
17
call of BdrvChildRole.drained_begin() must therefore be followed by a
18
BDRV_POLL_WHILE() that waits for the completion of requests.
19
20
Reported-by: Max Reitz <mreitz@redhat.com>
21
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
22
---
23
include/block/block.h | 8 ++++++++
24
include/block/block_int.h | 3 +++
25
block.c | 2 +-
26
block/io.c | 26 ++++++++++++++++++++------
27
4 files changed, 32 insertions(+), 7 deletions(-)
28
29
diff --git a/include/block/block.h b/include/block/block.h
30
index XXXXXXX..XXXXXXX 100644
31
--- a/include/block/block.h
32
+++ b/include/block/block.h
33
@@ -XXX,XX +XXX,XX @@ void bdrv_parent_drained_begin(BlockDriverState *bs, BdrvChild *ignore,
34
bool ignore_bds_parents);
35
36
/**
37
+ * bdrv_parent_drained_begin_single:
38
+ *
39
+ * Begin a quiesced section for the parent of @c. If @poll is true, wait for
40
+ * any pending activity to cease.
41
+ */
42
+void bdrv_parent_drained_begin_single(BdrvChild *c, bool poll);
43
+
44
+/**
45
* bdrv_parent_drained_end:
46
*
47
* End a quiesced section of all users of @bs. This is part of
48
diff --git a/include/block/block_int.h b/include/block/block_int.h
49
index XXXXXXX..XXXXXXX 100644
50
--- a/include/block/block_int.h
51
+++ b/include/block/block_int.h
52
@@ -XXX,XX +XXX,XX @@ struct BdrvChildRole {
53
* requests after returning from .drained_begin() until .drained_end() is
54
* called.
55
*
56
+ * These functions must not change the graph (and therefore also must not
57
+ * call aio_poll(), which could change the graph indirectly).
58
+ *
59
* Note that this can be nested. If drained_begin() was called twice, new
60
* I/O is allowed only after drained_end() was called twice, too.
61
*/
62
diff --git a/block.c b/block.c
63
index XXXXXXX..XXXXXXX 100644
64
--- a/block.c
65
+++ b/block.c
66
@@ -XXX,XX +XXX,XX @@ static void bdrv_replace_child_noperm(BdrvChild *child,
67
}
68
assert(num >= 0);
69
for (i = 0; i < num; i++) {
70
- child->role->drained_begin(child);
71
+ bdrv_parent_drained_begin_single(child, true);
72
}
73
}
74
75
diff --git a/block/io.c b/block/io.c
76
index XXXXXXX..XXXXXXX 100644
77
--- a/block/io.c
78
+++ b/block/io.c
79
@@ -XXX,XX +XXX,XX @@ void bdrv_parent_drained_begin(BlockDriverState *bs, BdrvChild *ignore,
80
if (c == ignore || (ignore_bds_parents && c->role->parent_is_bds)) {
81
continue;
82
}
83
- if (c->role->drained_begin) {
84
- c->role->drained_begin(c);
85
- }
86
+ bdrv_parent_drained_begin_single(c, false);
87
}
88
}
89
90
@@ -XXX,XX +XXX,XX @@ void bdrv_parent_drained_end(BlockDriverState *bs, BdrvChild *ignore,
91
}
92
}
93
94
+static bool bdrv_parent_drained_poll_single(BdrvChild *c)
95
+{
96
+ if (c->role->drained_poll) {
97
+ return c->role->drained_poll(c);
98
+ }
99
+ return false;
100
+}
101
+
102
static bool bdrv_parent_drained_poll(BlockDriverState *bs, BdrvChild *ignore,
103
bool ignore_bds_parents)
104
{
105
@@ -XXX,XX +XXX,XX @@ static bool bdrv_parent_drained_poll(BlockDriverState *bs, BdrvChild *ignore,
106
if (c == ignore || (ignore_bds_parents && c->role->parent_is_bds)) {
107
continue;
108
}
109
- if (c->role->drained_poll) {
110
- busy |= c->role->drained_poll(c);
111
- }
112
+ busy |= bdrv_parent_drained_poll_single(c);
113
}
114
115
return busy;
116
}
117
118
+void bdrv_parent_drained_begin_single(BdrvChild *c, bool poll)
119
+{
120
+ if (c->role->drained_begin) {
121
+ c->role->drained_begin(c);
122
+ }
123
+ if (poll) {
124
+ BDRV_POLL_WHILE(c->bs, bdrv_parent_drained_poll_single(c));
125
+ }
126
+}
127
+
128
static void bdrv_merge_limits(BlockLimits *dst, const BlockLimits *src)
129
{
130
dst->opt_transfer = MAX(dst->opt_transfer, src->opt_transfer);
131
--
132
2.13.6
133
134
diff view generated by jsdifflib
Deleted patch
1
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2
---
3
tests/test-bdrv-drain.c | 43 +++++++++++++++++++++++++++++++++++++++++++
4
1 file changed, 43 insertions(+)
5
1
6
diff --git a/tests/test-bdrv-drain.c b/tests/test-bdrv-drain.c
7
index XXXXXXX..XXXXXXX 100644
8
--- a/tests/test-bdrv-drain.c
9
+++ b/tests/test-bdrv-drain.c
10
@@ -XXX,XX +XXX,XX @@ static void test_detach_by_driver_cb(void)
11
test_detach_indirect(false);
12
}
13
14
+static void test_append_to_drained(void)
15
+{
16
+ BlockBackend *blk;
17
+ BlockDriverState *base, *overlay;
18
+ BDRVTestState *base_s, *overlay_s;
19
+
20
+ blk = blk_new(BLK_PERM_ALL, BLK_PERM_ALL);
21
+ base = bdrv_new_open_driver(&bdrv_test, "base", BDRV_O_RDWR, &error_abort);
22
+ base_s = base->opaque;
23
+ blk_insert_bs(blk, base, &error_abort);
24
+
25
+ overlay = bdrv_new_open_driver(&bdrv_test, "overlay", BDRV_O_RDWR,
26
+ &error_abort);
27
+ overlay_s = overlay->opaque;
28
+
29
+ do_drain_begin(BDRV_DRAIN, base);
30
+ g_assert_cmpint(base->quiesce_counter, ==, 1);
31
+ g_assert_cmpint(base_s->drain_count, ==, 1);
32
+ g_assert_cmpint(base->in_flight, ==, 0);
33
+
34
+ /* Takes ownership of overlay, so we don't have to unref it later */
35
+ bdrv_append(overlay, base, &error_abort);
36
+ g_assert_cmpint(base->in_flight, ==, 0);
37
+ g_assert_cmpint(overlay->in_flight, ==, 0);
38
+
39
+ g_assert_cmpint(base->quiesce_counter, ==, 1);
40
+ g_assert_cmpint(base_s->drain_count, ==, 1);
41
+ g_assert_cmpint(overlay->quiesce_counter, ==, 1);
42
+ g_assert_cmpint(overlay_s->drain_count, ==, 1);
43
+
44
+ do_drain_end(BDRV_DRAIN, base);
45
+
46
+ g_assert_cmpint(base->quiesce_counter, ==, 0);
47
+ g_assert_cmpint(base_s->drain_count, ==, 0);
48
+ g_assert_cmpint(overlay->quiesce_counter, ==, 0);
49
+ g_assert_cmpint(overlay_s->drain_count, ==, 0);
50
+
51
+ bdrv_unref(base);
52
+ blk_unref(blk);
53
+}
54
+
55
int main(int argc, char **argv)
56
{
57
int ret;
58
@@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv)
59
g_test_add_func("/bdrv-drain/detach/parent_cb", test_detach_by_parent_cb);
60
g_test_add_func("/bdrv-drain/detach/driver_cb", test_detach_by_driver_cb);
61
62
+ g_test_add_func("/bdrv-drain/attach/drain", test_append_to_drained);
63
+
64
ret = g_test_run();
65
qemu_event_destroy(&done_event);
66
return ret;
67
--
68
2.13.6
69
70
diff view generated by jsdifflib
Deleted patch
1
If the virtual disk size isn't aligned to full clusters,
2
bdrv_co_do_copy_on_readv() may get pnum == 0 before having the full
3
cluster completed, which will let it run into an assertion failure:
4
1
5
qemu-io: block/io.c:1203: bdrv_co_do_copy_on_readv: Assertion `skip_bytes < pnum' failed.
6
7
Check for EOF, assert that we read at least as much as the read request
8
originally wanted to have (which is true at EOF because otherwise
9
bdrv_check_byte_request() would already have returned an error) and
10
return success early even though we couldn't copy the full cluster.
11
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
---
14
block/io.c | 6 ++++++
15
tests/qemu-iotests/197 | 9 +++++++++
16
tests/qemu-iotests/197.out | 8 ++++++++
17
3 files changed, 23 insertions(+)
18
19
diff --git a/block/io.c b/block/io.c
20
index XXXXXXX..XXXXXXX 100644
21
--- a/block/io.c
22
+++ b/block/io.c
23
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_co_do_copy_on_readv(BdrvChild *child,
24
pnum = MIN(cluster_bytes, max_transfer);
25
}
26
27
+ /* Stop at EOF if the image ends in the middle of the cluster */
28
+ if (ret == 0 && pnum == 0) {
29
+ assert(progress >= bytes);
30
+ break;
31
+ }
32
+
33
assert(skip_bytes < pnum);
34
35
if (ret <= 0) {
36
diff --git a/tests/qemu-iotests/197 b/tests/qemu-iotests/197
37
index XXXXXXX..XXXXXXX 100755
38
--- a/tests/qemu-iotests/197
39
+++ b/tests/qemu-iotests/197
40
@@ -XXX,XX +XXX,XX @@ $QEMU_IO -f qcow2 -c map "$TEST_WRAP"
41
_check_test_img
42
$QEMU_IMG compare -f $IMGFMT -F qcow2 "$TEST_IMG" "$TEST_WRAP"
43
44
+echo
45
+echo '=== Partial final cluster ==='
46
+echo
47
+
48
+_make_test_img 1024
49
+$QEMU_IO -f $IMGFMT -C -c 'read 0 1024' "$TEST_IMG" | _filter_qemu_io
50
+$QEMU_IO -f $IMGFMT -c map "$TEST_IMG"
51
+_check_test_img
52
+
53
# success, all done
54
echo '*** done'
55
status=0
56
diff --git a/tests/qemu-iotests/197.out b/tests/qemu-iotests/197.out
57
index XXXXXXX..XXXXXXX 100644
58
--- a/tests/qemu-iotests/197.out
59
+++ b/tests/qemu-iotests/197.out
60
@@ -XXX,XX +XXX,XX @@ can't open device TEST_DIR/t.wrap.qcow2: Can't use copy-on-read on read-only dev
61
1023.938 MiB (0x3fff0000) bytes not allocated at offset 3 GiB (0xc0010000)
62
No errors were found on the image.
63
Images are identical.
64
+
65
+=== Partial final cluster ===
66
+
67
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1024
68
+read 1024/1024 bytes at offset 0
69
+1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
70
+1 KiB (0x400) bytes allocated at offset 0 bytes (0x0)
71
+No errors were found on the image.
72
*** done
73
--
74
2.13.6
75
76
diff view generated by jsdifflib
Deleted patch
1
From: Fam Zheng <famz@redhat.com>
2
1
3
Luks needs special parameters to operate the image. Since this test is
4
focusing on image fleecing, skip skip that format.
5
6
Signed-off-by: Fam Zheng <famz@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
---
9
tests/qemu-iotests/222 | 2 ++
10
1 file changed, 2 insertions(+)
11
12
diff --git a/tests/qemu-iotests/222 b/tests/qemu-iotests/222
13
index XXXXXXX..XXXXXXX 100644
14
--- a/tests/qemu-iotests/222
15
+++ b/tests/qemu-iotests/222
16
@@ -XXX,XX +XXX,XX @@ import iotests
17
from iotests import log, qemu_img, qemu_io, qemu_io_silent
18
19
iotests.verify_platform(['linux'])
20
+iotests.verify_image_format(supported_fmts=['qcow2', 'qcow', 'qed', 'vmdk',
21
+ 'vhdx', 'raw'])
22
23
patterns = [("0x5d", "0", "64k"),
24
("0xd5", "1M", "64k"),
25
--
26
2.13.6
27
28
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
Here two things are fixed:
4
5
1. Architecture
6
7
On each recursion step, we go to the child of src or dst, only for one
8
of them. So, it's wrong to create tracked requests for both on each
9
step. It leads to tracked requests duplication.
10
11
2. Wait for serializing requests on write path independently of
12
BDRV_REQ_NO_SERIALISING
13
14
Before commit 9ded4a01149 "backup: Use copy offloading",
15
BDRV_REQ_NO_SERIALISING was used for only one case: read in
16
copy-on-write operation during backup. Also, the flag was handled only
17
on read path (in bdrv_co_preadv and bdrv_aligned_preadv).
18
19
After 9ded4a01149, flag is used for not waiting serializing operations
20
on backup target (in same case of copy-on-write operation). This
21
behavior change is unsubstantiated and potentially dangerous, let's
22
drop it and add additional asserts and documentation.
23
24
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
25
Reviewed-by: Fam Zheng <famz@redhat.com>
26
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
27
---
28
include/block/block.h | 12 ++++++++++++
29
block/io.c | 42 +++++++++++++++++++++++++++---------------
30
2 files changed, 39 insertions(+), 15 deletions(-)
31
32
diff --git a/include/block/block.h b/include/block/block.h
33
index XXXXXXX..XXXXXXX 100644
34
--- a/include/block/block.h
35
+++ b/include/block/block.h
36
@@ -XXX,XX +XXX,XX @@ typedef enum {
37
* opened with BDRV_O_UNMAP.
38
*/
39
BDRV_REQ_MAY_UNMAP = 0x4,
40
+
41
+ /*
42
+ * The BDRV_REQ_NO_SERIALISING flag is only valid for reads and means that
43
+ * we don't want wait_serialising_requests() during the read operation.
44
+ *
45
+ * This flag is used for backup copy-on-write operations, when we need to
46
+ * read old data before write (write notifier triggered). It is okay since
47
+ * we already waited for other serializing requests in the initiating write
48
+ * (see bdrv_aligned_pwritev), and it is necessary if the initiating write
49
+ * is already serializing (without the flag, the read would deadlock
50
+ * waiting for the serialising write to complete).
51
+ */
52
BDRV_REQ_NO_SERIALISING = 0x8,
53
BDRV_REQ_FUA = 0x10,
54
BDRV_REQ_WRITE_COMPRESSED = 0x20,
55
diff --git a/block/io.c b/block/io.c
56
index XXXXXXX..XXXXXXX 100644
57
--- a/block/io.c
58
+++ b/block/io.c
59
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_aligned_pwritev(BdrvChild *child,
60
max_transfer = QEMU_ALIGN_DOWN(MIN_NON_ZERO(bs->bl.max_transfer, INT_MAX),
61
align);
62
63
+ /* BDRV_REQ_NO_SERIALISING is only for read operation */
64
+ assert(!(flags & BDRV_REQ_NO_SERIALISING));
65
waited = wait_serialising_requests(req);
66
assert(!waited || !req->serialising);
67
assert(req->overlap_offset <= offset);
68
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_co_copy_range_internal(BdrvChild *src,
69
BdrvRequestFlags flags,
70
bool recurse_src)
71
{
72
- BdrvTrackedRequest src_req, dst_req;
73
+ BdrvTrackedRequest req;
74
int ret;
75
76
if (!dst || !dst->bs) {
77
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_co_copy_range_internal(BdrvChild *src,
78
|| src->bs->encrypted || dst->bs->encrypted) {
79
return -ENOTSUP;
80
}
81
- bdrv_inc_in_flight(src->bs);
82
- bdrv_inc_in_flight(dst->bs);
83
- tracked_request_begin(&src_req, src->bs, src_offset,
84
- bytes, BDRV_TRACKED_READ);
85
- tracked_request_begin(&dst_req, dst->bs, dst_offset,
86
- bytes, BDRV_TRACKED_WRITE);
87
88
- if (!(flags & BDRV_REQ_NO_SERIALISING)) {
89
- wait_serialising_requests(&src_req);
90
- wait_serialising_requests(&dst_req);
91
- }
92
if (recurse_src) {
93
+ bdrv_inc_in_flight(src->bs);
94
+ tracked_request_begin(&req, src->bs, src_offset, bytes,
95
+ BDRV_TRACKED_READ);
96
+
97
+ if (!(flags & BDRV_REQ_NO_SERIALISING)) {
98
+ wait_serialising_requests(&req);
99
+ }
100
+
101
ret = src->bs->drv->bdrv_co_copy_range_from(src->bs,
102
src, src_offset,
103
dst, dst_offset,
104
bytes, flags);
105
+
106
+ tracked_request_end(&req);
107
+ bdrv_dec_in_flight(src->bs);
108
} else {
109
+ bdrv_inc_in_flight(dst->bs);
110
+ tracked_request_begin(&req, dst->bs, dst_offset, bytes,
111
+ BDRV_TRACKED_WRITE);
112
+
113
+ /* BDRV_REQ_NO_SERIALISING is only for read operation,
114
+ * so we ignore it in flags.
115
+ */
116
+ wait_serialising_requests(&req);
117
+
118
ret = dst->bs->drv->bdrv_co_copy_range_to(dst->bs,
119
src, src_offset,
120
dst, dst_offset,
121
bytes, flags);
122
+
123
+ tracked_request_end(&req);
124
+ bdrv_dec_in_flight(dst->bs);
125
}
126
- tracked_request_end(&src_req);
127
- tracked_request_end(&dst_req);
128
- bdrv_dec_in_flight(src->bs);
129
- bdrv_dec_in_flight(dst->bs);
130
+
131
return ret;
132
}
133
134
--
135
2.13.6
136
137
diff view generated by jsdifflib
1
From: Fam Zheng <famz@redhat.com>
1
From: Denis Rastyogin <gerben@altlinux.org>
2
2
3
Truncation is the last to convert from open coded req handling to
3
This error was discovered by fuzzing qemu-img.
4
reusing helpers. This time the permission check in prepare has to adapt
5
to the new caller: it checks a different permission bit, and doesn't
6
trigger the before write notifier.
7
4
8
Also, truncation should always trigger a bs->total_sectors update and in
5
This commit fixes a division by zero error in the bench_cb() function
9
turn call parent resize_cb. Update the condition in finish helper, too.
6
that occurs when using the bench command with a zero-sized image.
10
7
11
It's intended to do a duplicated bs->read_only check before calling
8
The issue arises because b->image_size can be zero, leading to a
12
bdrv_co_write_req_prepare() so that we can be more informative with the
9
division by zero in the modulo operation (b->offset %= b->image_size).
13
error message, as bdrv_co_write_req_prepare() doesn't have Error
10
This patch adds a check for b->image_size == 0 and resets b->offset
14
parameter.
11
to 0 in such cases, preventing the error.
15
12
16
Signed-off-by: Fam Zheng <famz@redhat.com>
13
Signed-off-by: Denis Rastyogin <gerben@altlinux.org>
14
Message-ID: <20250318101933.255617-1-gerben@altlinux.org>
15
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
17
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
16
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
18
---
17
---
19
block/io.c | 55 +++++++++++++++++++++++++++++++++++--------------------
18
qemu-img.c | 6 +++++-
20
1 file changed, 35 insertions(+), 20 deletions(-)
19
1 file changed, 5 insertions(+), 1 deletion(-)
21
20
22
diff --git a/block/io.c b/block/io.c
21
diff --git a/qemu-img.c b/qemu-img.c
23
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
24
--- a/block/io.c
23
--- a/qemu-img.c
25
+++ b/block/io.c
24
+++ b/qemu-img.c
26
@@ -XXX,XX +XXX,XX @@ bdrv_co_write_req_prepare(BdrvChild *child, int64_t offset, uint64_t bytes,
25
@@ -XXX,XX +XXX,XX @@ static void bench_cb(void *opaque, int ret)
27
is_request_serialising_and_aligned(req));
26
*/
28
assert(req->overlap_offset <= offset);
27
b->in_flight++;
29
assert(offset + bytes <= req->overlap_offset + req->overlap_bytes);
28
b->offset += b->step;
30
+ assert(end_sector <= bs->total_sectors || child->perm & BLK_PERM_RESIZE);
29
- b->offset %= b->image_size;
31
30
+ if (b->image_size == 0) {
32
- if (flags & BDRV_REQ_WRITE_UNCHANGED) {
31
+ b->offset = 0;
33
- assert(child->perm & (BLK_PERM_WRITE_UNCHANGED | BLK_PERM_WRITE));
34
- } else {
35
- assert(child->perm & BLK_PERM_WRITE);
36
+ switch (req->type) {
37
+ case BDRV_TRACKED_WRITE:
38
+ case BDRV_TRACKED_DISCARD:
39
+ if (flags & BDRV_REQ_WRITE_UNCHANGED) {
40
+ assert(child->perm & (BLK_PERM_WRITE_UNCHANGED | BLK_PERM_WRITE));
41
+ } else {
32
+ } else {
42
+ assert(child->perm & BLK_PERM_WRITE);
33
+ b->offset %= b->image_size;
43
+ }
34
+ }
44
+ return notifier_with_return_list_notify(&bs->before_write_notifiers,
35
if (b->write) {
45
+ req);
36
acb = blk_aio_pwritev(b->blk, offset, b->qiov, 0, bench_cb, b);
46
+ case BDRV_TRACKED_TRUNCATE:
37
} else {
47
+ assert(child->perm & BLK_PERM_RESIZE);
48
+ return 0;
49
+ default:
50
+ abort();
51
}
52
- assert(end_sector <= bs->total_sectors || child->perm & BLK_PERM_RESIZE);
53
- return notifier_with_return_list_notify(&bs->before_write_notifiers, req);
54
}
55
56
static inline void coroutine_fn
57
@@ -XXX,XX +XXX,XX @@ bdrv_co_write_req_finish(BdrvChild *child, int64_t offset, uint64_t bytes,
58
* beyond EOF cannot expand the image anyway.
59
*/
60
if (ret == 0 &&
61
- end_sector > bs->total_sectors &&
62
- req->type != BDRV_TRACKED_DISCARD) {
63
+ (req->type == BDRV_TRACKED_TRUNCATE ||
64
+ end_sector > bs->total_sectors) &&
65
+ req->type != BDRV_TRACKED_DISCARD) {
66
bs->total_sectors = end_sector;
67
bdrv_parent_cb_resize(bs);
68
bdrv_dirty_bitmap_truncate(bs, end_sector << BDRV_SECTOR_BITS);
69
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset,
70
int64_t old_size, new_bytes;
71
int ret;
72
73
- assert(child->perm & BLK_PERM_RESIZE);
74
75
/* if bs->drv == NULL, bs is closed, so there's nothing to do here */
76
if (!drv) {
77
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset,
78
* concurrently or they might be overwritten by preallocation. */
79
if (new_bytes) {
80
mark_request_serialising(&req, 1);
81
- wait_serialising_requests(&req);
82
+ }
83
+ if (bs->read_only) {
84
+ error_setg(errp, "Image is read-only");
85
+ ret = -EACCES;
86
+ goto out;
87
+ }
88
+ ret = bdrv_co_write_req_prepare(child, offset - new_bytes, new_bytes, &req,
89
+ 0);
90
+ if (ret < 0) {
91
+ error_setg_errno(errp, -ret,
92
+ "Failed to prepare request for truncation");
93
+ goto out;
94
}
95
96
if (!drv->bdrv_co_truncate) {
97
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset,
98
ret = -ENOTSUP;
99
goto out;
100
}
101
- if (bs->read_only) {
102
- error_setg(errp, "Image is read-only");
103
- ret = -EACCES;
104
- goto out;
105
- }
106
-
107
- assert(!(bs->open_flags & BDRV_O_INACTIVE));
108
109
ret = drv->bdrv_co_truncate(bs, offset, prealloc, errp);
110
if (ret < 0) {
111
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset,
112
} else {
113
offset = bs->total_sectors * BDRV_SECTOR_SIZE;
114
}
115
- bdrv_dirty_bitmap_truncate(bs, offset);
116
- bdrv_parent_cb_resize(bs);
117
- atomic_inc(&bs->write_gen);
118
+ /* It's possible that truncation succeeded but refresh_total_sectors
119
+ * failed, but the latter doesn't affect how we should finish the request.
120
+ * Pass 0 as the last parameter so that dirty bitmaps etc. are handled. */
121
+ bdrv_co_write_req_finish(child, offset - new_bytes, new_bytes, &req, 0);
122
123
out:
124
tracked_request_end(&req);
125
--
38
--
126
2.13.6
39
2.49.0
127
128
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
qcow2_refresh_limits() assumes that s->crypto is non-NULL whenever
2
bs->encrypted is true. This is actually not the case: qcow2_do_open()
3
allows to open an image with a missing crypto header for BDRV_O_NO_IO,
4
and then bs->encrypted is true, but s->crypto is still NULL.
2
5
3
Pass read flags and write flags separately. This is needed to handle
6
It doesn't make sense to open an invalid image, so remove the exception
4
coming BDRV_REQ_NO_SERIALISING clearly in following patches.
7
for BDRV_O_NO_IO. This catches the problem early and any code that makes
8
the same assumption is safe now.
5
9
6
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
10
At the same time, in the name of defensive programming, we shouldn't
7
Reviewed-by: Fam Zheng <famz@redhat.com>
11
make the assumption in the first place. Let qcow2_refresh_limits() check
12
s->crypto rather than bs->encrypted. If s->crypto is NULL, it also can't
13
make any requirement on request alignment.
14
15
Finally, start a qcow2-encryption test case that only serves as a
16
regression test for this crash for now.
17
18
Reported-by: Leonid Reviakin <L.reviakin@fobos-nt.ru>
19
Reported-by: Denis Rastyogin <gerben@altlinux.org>
20
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
21
Message-ID: <20250318201143.70657-1-kwolf@redhat.com>
22
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
23
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
24
---
10
include/block/block.h | 3 ++-
25
block/qcow2.c | 4 +-
11
include/block/block_int.h | 14 +++++++++----
26
tests/qemu-iotests/tests/qcow2-encryption | 75 +++++++++++++++++++
12
include/sysemu/block-backend.h | 3 ++-
27
tests/qemu-iotests/tests/qcow2-encryption.out | 32 ++++++++
13
block/backup.c | 2 +-
28
3 files changed, 109 insertions(+), 2 deletions(-)
14
block/block-backend.c | 5 +++--
29
create mode 100755 tests/qemu-iotests/tests/qcow2-encryption
15
block/file-posix.c | 21 +++++++++++--------
30
create mode 100644 tests/qemu-iotests/tests/qcow2-encryption.out
16
block/io.c | 46 +++++++++++++++++++++++-------------------
17
block/iscsi.c | 9 ++++++---
18
block/qcow2.c | 20 +++++++++---------
19
block/raw-format.c | 24 ++++++++++++++--------
20
qemu-img.c | 2 +-
21
11 files changed, 90 insertions(+), 59 deletions(-)
22
31
23
diff --git a/include/block/block.h b/include/block/block.h
24
index XXXXXXX..XXXXXXX 100644
25
--- a/include/block/block.h
26
+++ b/include/block/block.h
27
@@ -XXX,XX +XXX,XX @@ void bdrv_unregister_buf(BlockDriverState *bs, void *host);
28
**/
29
int coroutine_fn bdrv_co_copy_range(BdrvChild *src, uint64_t src_offset,
30
BdrvChild *dst, uint64_t dst_offset,
31
- uint64_t bytes, BdrvRequestFlags flags);
32
+ uint64_t bytes, BdrvRequestFlags read_flags,
33
+ BdrvRequestFlags write_flags);
34
#endif
35
diff --git a/include/block/block_int.h b/include/block/block_int.h
36
index XXXXXXX..XXXXXXX 100644
37
--- a/include/block/block_int.h
38
+++ b/include/block/block_int.h
39
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
40
BdrvChild *dst,
41
uint64_t dst_offset,
42
uint64_t bytes,
43
- BdrvRequestFlags flags);
44
+ BdrvRequestFlags read_flags,
45
+ BdrvRequestFlags write_flags);
46
47
/* Map [offset, offset + nbytes) range onto a child of bs to copy data to,
48
* and invoke bdrv_co_copy_range_to(child, src, ...), or perform the copy
49
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
50
BdrvChild *dst,
51
uint64_t dst_offset,
52
uint64_t bytes,
53
- BdrvRequestFlags flags);
54
+ BdrvRequestFlags read_flags,
55
+ BdrvRequestFlags write_flags);
56
57
/*
58
* Building block for bdrv_block_status[_above] and
59
@@ -XXX,XX +XXX,XX @@ void blockdev_close_all_bdrv_states(void);
60
61
int coroutine_fn bdrv_co_copy_range_from(BdrvChild *src, uint64_t src_offset,
62
BdrvChild *dst, uint64_t dst_offset,
63
- uint64_t bytes, BdrvRequestFlags flags);
64
+ uint64_t bytes,
65
+ BdrvRequestFlags read_flags,
66
+ BdrvRequestFlags write_flags);
67
int coroutine_fn bdrv_co_copy_range_to(BdrvChild *src, uint64_t src_offset,
68
BdrvChild *dst, uint64_t dst_offset,
69
- uint64_t bytes, BdrvRequestFlags flags);
70
+ uint64_t bytes,
71
+ BdrvRequestFlags read_flags,
72
+ BdrvRequestFlags write_flags);
73
74
int refresh_total_sectors(BlockDriverState *bs, int64_t hint);
75
76
diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h
77
index XXXXXXX..XXXXXXX 100644
78
--- a/include/sysemu/block-backend.h
79
+++ b/include/sysemu/block-backend.h
80
@@ -XXX,XX +XXX,XX @@ void blk_unregister_buf(BlockBackend *blk, void *host);
81
82
int coroutine_fn blk_co_copy_range(BlockBackend *blk_in, int64_t off_in,
83
BlockBackend *blk_out, int64_t off_out,
84
- int bytes, BdrvRequestFlags flags);
85
+ int bytes, BdrvRequestFlags read_flags,
86
+ BdrvRequestFlags write_flags);
87
88
#endif
89
diff --git a/block/backup.c b/block/backup.c
90
index XXXXXXX..XXXXXXX 100644
91
--- a/block/backup.c
92
+++ b/block/backup.c
93
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn backup_cow_with_offload(BackupBlockJob *job,
94
hbitmap_reset(job->copy_bitmap, start / job->cluster_size,
95
nr_clusters);
96
ret = blk_co_copy_range(blk, start, job->target, start, nbytes,
97
- is_write_notifier ? BDRV_REQ_NO_SERIALISING : 0);
98
+ is_write_notifier ? BDRV_REQ_NO_SERIALISING : 0, 0);
99
if (ret < 0) {
100
trace_backup_do_cow_copy_range_fail(job, start, ret);
101
hbitmap_set(job->copy_bitmap, start / job->cluster_size,
102
diff --git a/block/block-backend.c b/block/block-backend.c
103
index XXXXXXX..XXXXXXX 100644
104
--- a/block/block-backend.c
105
+++ b/block/block-backend.c
106
@@ -XXX,XX +XXX,XX @@ void blk_unregister_buf(BlockBackend *blk, void *host)
107
108
int coroutine_fn blk_co_copy_range(BlockBackend *blk_in, int64_t off_in,
109
BlockBackend *blk_out, int64_t off_out,
110
- int bytes, BdrvRequestFlags flags)
111
+ int bytes, BdrvRequestFlags read_flags,
112
+ BdrvRequestFlags write_flags)
113
{
114
int r;
115
r = blk_check_byte_request(blk_in, off_in, bytes);
116
@@ -XXX,XX +XXX,XX @@ int coroutine_fn blk_co_copy_range(BlockBackend *blk_in, int64_t off_in,
117
}
118
return bdrv_co_copy_range(blk_in->root, off_in,
119
blk_out->root, off_out,
120
- bytes, flags);
121
+ bytes, read_flags, write_flags);
122
}
123
diff --git a/block/file-posix.c b/block/file-posix.c
124
index XXXXXXX..XXXXXXX 100644
125
--- a/block/file-posix.c
126
+++ b/block/file-posix.c
127
@@ -XXX,XX +XXX,XX @@ static void raw_abort_perm_update(BlockDriverState *bs)
128
raw_handle_perm_lock(bs, RAW_PL_ABORT, 0, 0, NULL);
129
}
130
131
-static int coroutine_fn raw_co_copy_range_from(BlockDriverState *bs,
132
- BdrvChild *src, uint64_t src_offset,
133
- BdrvChild *dst, uint64_t dst_offset,
134
- uint64_t bytes, BdrvRequestFlags flags)
135
+static int coroutine_fn raw_co_copy_range_from(
136
+ BlockDriverState *bs, BdrvChild *src, uint64_t src_offset,
137
+ BdrvChild *dst, uint64_t dst_offset, uint64_t bytes,
138
+ BdrvRequestFlags read_flags, BdrvRequestFlags write_flags)
139
{
140
- return bdrv_co_copy_range_to(src, src_offset, dst, dst_offset, bytes, flags);
141
+ return bdrv_co_copy_range_to(src, src_offset, dst, dst_offset, bytes,
142
+ read_flags, write_flags);
143
}
144
145
static int coroutine_fn raw_co_copy_range_to(BlockDriverState *bs,
146
- BdrvChild *src, uint64_t src_offset,
147
- BdrvChild *dst, uint64_t dst_offset,
148
- uint64_t bytes, BdrvRequestFlags flags)
149
+ BdrvChild *src,
150
+ uint64_t src_offset,
151
+ BdrvChild *dst,
152
+ uint64_t dst_offset,
153
+ uint64_t bytes,
154
+ BdrvRequestFlags read_flags,
155
+ BdrvRequestFlags write_flags)
156
{
157
BDRVRawState *s = bs->opaque;
158
BDRVRawState *src_s;
159
diff --git a/block/io.c b/block/io.c
160
index XXXXXXX..XXXXXXX 100644
161
--- a/block/io.c
162
+++ b/block/io.c
163
@@ -XXX,XX +XXX,XX @@ void bdrv_unregister_buf(BlockDriverState *bs, void *host)
164
}
165
}
166
167
-static int coroutine_fn bdrv_co_copy_range_internal(BdrvChild *src,
168
- uint64_t src_offset,
169
- BdrvChild *dst,
170
- uint64_t dst_offset,
171
- uint64_t bytes,
172
- BdrvRequestFlags flags,
173
- bool recurse_src)
174
+static int coroutine_fn bdrv_co_copy_range_internal(
175
+ BdrvChild *src, uint64_t src_offset, BdrvChild *dst,
176
+ uint64_t dst_offset, uint64_t bytes,
177
+ BdrvRequestFlags read_flags, BdrvRequestFlags write_flags,
178
+ bool recurse_src)
179
{
180
BdrvTrackedRequest req;
181
int ret;
182
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_co_copy_range_internal(BdrvChild *src,
183
if (ret) {
184
return ret;
185
}
186
- if (flags & BDRV_REQ_ZERO_WRITE) {
187
- return bdrv_co_pwrite_zeroes(dst, dst_offset, bytes, flags);
188
+ if (write_flags & BDRV_REQ_ZERO_WRITE) {
189
+ return bdrv_co_pwrite_zeroes(dst, dst_offset, bytes, write_flags);
190
}
191
192
if (!src || !src->bs) {
193
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_co_copy_range_internal(BdrvChild *src,
194
tracked_request_begin(&req, src->bs, src_offset, bytes,
195
BDRV_TRACKED_READ);
196
197
- if (!(flags & BDRV_REQ_NO_SERIALISING)) {
198
+ if (!(read_flags & BDRV_REQ_NO_SERIALISING)) {
199
wait_serialising_requests(&req);
200
}
201
202
ret = src->bs->drv->bdrv_co_copy_range_from(src->bs,
203
src, src_offset,
204
dst, dst_offset,
205
- bytes, flags);
206
+ bytes,
207
+ read_flags, write_flags);
208
209
tracked_request_end(&req);
210
bdrv_dec_in_flight(src->bs);
211
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_co_copy_range_internal(BdrvChild *src,
212
tracked_request_begin(&req, dst->bs, dst_offset, bytes,
213
BDRV_TRACKED_WRITE);
214
215
- /* BDRV_REQ_NO_SERIALISING is only for read operation,
216
- * so we ignore it in flags.
217
- */
218
+ /* BDRV_REQ_NO_SERIALISING is only for read operation */
219
+ assert(!(write_flags & BDRV_REQ_NO_SERIALISING));
220
wait_serialising_requests(&req);
221
222
ret = dst->bs->drv->bdrv_co_copy_range_to(dst->bs,
223
src, src_offset,
224
dst, dst_offset,
225
- bytes, flags);
226
+ bytes,
227
+ read_flags, write_flags);
228
229
tracked_request_end(&req);
230
bdrv_dec_in_flight(dst->bs);
231
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_co_copy_range_internal(BdrvChild *src,
232
* semantics. */
233
int coroutine_fn bdrv_co_copy_range_from(BdrvChild *src, uint64_t src_offset,
234
BdrvChild *dst, uint64_t dst_offset,
235
- uint64_t bytes, BdrvRequestFlags flags)
236
+ uint64_t bytes,
237
+ BdrvRequestFlags read_flags,
238
+ BdrvRequestFlags write_flags)
239
{
240
return bdrv_co_copy_range_internal(src, src_offset, dst, dst_offset,
241
- bytes, flags, true);
242
+ bytes, read_flags, write_flags, true);
243
}
244
245
/* Copy range from @src to @dst.
246
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_copy_range_from(BdrvChild *src, uint64_t src_offset,
247
* semantics. */
248
int coroutine_fn bdrv_co_copy_range_to(BdrvChild *src, uint64_t src_offset,
249
BdrvChild *dst, uint64_t dst_offset,
250
- uint64_t bytes, BdrvRequestFlags flags)
251
+ uint64_t bytes,
252
+ BdrvRequestFlags read_flags,
253
+ BdrvRequestFlags write_flags)
254
{
255
return bdrv_co_copy_range_internal(src, src_offset, dst, dst_offset,
256
- bytes, flags, false);
257
+ bytes, read_flags, write_flags, false);
258
}
259
260
int coroutine_fn bdrv_co_copy_range(BdrvChild *src, uint64_t src_offset,
261
BdrvChild *dst, uint64_t dst_offset,
262
- uint64_t bytes, BdrvRequestFlags flags)
263
+ uint64_t bytes, BdrvRequestFlags read_flags,
264
+ BdrvRequestFlags write_flags)
265
{
266
return bdrv_co_copy_range_from(src, src_offset,
267
dst, dst_offset,
268
- bytes, flags);
269
+ bytes, read_flags, write_flags);
270
}
271
272
static void bdrv_parent_cb_resize(BlockDriverState *bs)
273
diff --git a/block/iscsi.c b/block/iscsi.c
274
index XXXXXXX..XXXXXXX 100644
275
--- a/block/iscsi.c
276
+++ b/block/iscsi.c
277
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn iscsi_co_copy_range_from(BlockDriverState *bs,
278
BdrvChild *dst,
279
uint64_t dst_offset,
280
uint64_t bytes,
281
- BdrvRequestFlags flags)
282
+ BdrvRequestFlags read_flags,
283
+ BdrvRequestFlags write_flags)
284
{
285
- return bdrv_co_copy_range_to(src, src_offset, dst, dst_offset, bytes, flags);
286
+ return bdrv_co_copy_range_to(src, src_offset, dst, dst_offset, bytes,
287
+ read_flags, write_flags);
288
}
289
290
static struct scsi_task *iscsi_xcopy_task(int param_len)
291
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn iscsi_co_copy_range_to(BlockDriverState *bs,
292
BdrvChild *dst,
293
uint64_t dst_offset,
294
uint64_t bytes,
295
- BdrvRequestFlags flags)
296
+ BdrvRequestFlags read_flags,
297
+ BdrvRequestFlags write_flags)
298
{
299
IscsiLun *dst_lun = dst->bs->opaque;
300
IscsiLun *src_lun;
301
diff --git a/block/qcow2.c b/block/qcow2.c
32
diff --git a/block/qcow2.c b/block/qcow2.c
302
index XXXXXXX..XXXXXXX 100644
33
index XXXXXXX..XXXXXXX 100644
303
--- a/block/qcow2.c
34
--- a/block/qcow2.c
304
+++ b/block/qcow2.c
35
+++ b/block/qcow2.c
305
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn
36
@@ -XXX,XX +XXX,XX @@ qcow2_do_open(BlockDriverState *bs, QDict *options, int flags,
306
qcow2_co_copy_range_from(BlockDriverState *bs,
37
ret = -EINVAL;
307
BdrvChild *src, uint64_t src_offset,
38
goto fail;
308
BdrvChild *dst, uint64_t dst_offset,
39
}
309
- uint64_t bytes, BdrvRequestFlags flags)
40
- } else if (!(flags & BDRV_O_NO_IO)) {
310
+ uint64_t bytes, BdrvRequestFlags read_flags,
41
+ } else {
311
+ BdrvRequestFlags write_flags)
42
error_setg(errp, "Missing CRYPTO header for crypt method %d",
43
s->crypt_method_header);
44
ret = -EINVAL;
45
@@ -XXX,XX +XXX,XX @@ static void qcow2_refresh_limits(BlockDriverState *bs, Error **errp)
312
{
46
{
313
BDRVQcow2State *s = bs->opaque;
47
BDRVQcow2State *s = bs->opaque;
314
int ret;
48
315
unsigned int cur_bytes; /* number of bytes in current iteration */
49
- if (bs->encrypted) {
316
BdrvChild *child = NULL;
50
+ if (s->crypto) {
317
- BdrvRequestFlags cur_flags;
51
/* Encryption works on a sector granularity */
318
+ BdrvRequestFlags cur_write_flags;
52
bs->bl.request_alignment = qcrypto_block_get_sector_size(s->crypto);
319
320
assert(!bs->encrypted);
321
qemu_co_mutex_lock(&s->lock);
322
@@ -XXX,XX +XXX,XX @@ qcow2_co_copy_range_from(BlockDriverState *bs,
323
uint64_t copy_offset = 0;
324
/* prepare next request */
325
cur_bytes = MIN(bytes, INT_MAX);
326
- cur_flags = flags;
327
+ cur_write_flags = write_flags;
328
329
ret = qcow2_get_cluster_offset(bs, src_offset, &cur_bytes, &copy_offset);
330
if (ret < 0) {
331
@@ -XXX,XX +XXX,XX @@ qcow2_co_copy_range_from(BlockDriverState *bs,
332
if (bs->backing && bs->backing->bs) {
333
int64_t backing_length = bdrv_getlength(bs->backing->bs);
334
if (src_offset >= backing_length) {
335
- cur_flags |= BDRV_REQ_ZERO_WRITE;
336
+ cur_write_flags |= BDRV_REQ_ZERO_WRITE;
337
} else {
338
child = bs->backing;
339
cur_bytes = MIN(cur_bytes, backing_length - src_offset);
340
copy_offset = src_offset;
341
}
342
} else {
343
- cur_flags |= BDRV_REQ_ZERO_WRITE;
344
+ cur_write_flags |= BDRV_REQ_ZERO_WRITE;
345
}
346
break;
347
348
case QCOW2_CLUSTER_ZERO_PLAIN:
349
case QCOW2_CLUSTER_ZERO_ALLOC:
350
- cur_flags |= BDRV_REQ_ZERO_WRITE;
351
+ cur_write_flags |= BDRV_REQ_ZERO_WRITE;
352
break;
353
354
case QCOW2_CLUSTER_COMPRESSED:
355
@@ -XXX,XX +XXX,XX @@ qcow2_co_copy_range_from(BlockDriverState *bs,
356
ret = bdrv_co_copy_range_from(child,
357
copy_offset,
358
dst, dst_offset,
359
- cur_bytes, cur_flags);
360
+ cur_bytes, read_flags, cur_write_flags);
361
qemu_co_mutex_lock(&s->lock);
362
if (ret < 0) {
363
goto out;
364
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn
365
qcow2_co_copy_range_to(BlockDriverState *bs,
366
BdrvChild *src, uint64_t src_offset,
367
BdrvChild *dst, uint64_t dst_offset,
368
- uint64_t bytes, BdrvRequestFlags flags)
369
+ uint64_t bytes, BdrvRequestFlags read_flags,
370
+ BdrvRequestFlags write_flags)
371
{
372
BDRVQcow2State *s = bs->opaque;
373
int offset_in_cluster;
374
@@ -XXX,XX +XXX,XX @@ qcow2_co_copy_range_to(BlockDriverState *bs,
375
ret = bdrv_co_copy_range_to(src, src_offset,
376
bs->file,
377
cluster_offset + offset_in_cluster,
378
- cur_bytes, flags);
379
+ cur_bytes, read_flags, write_flags);
380
qemu_co_mutex_lock(&s->lock);
381
if (ret < 0) {
382
goto fail;
383
diff --git a/block/raw-format.c b/block/raw-format.c
384
index XXXXXXX..XXXXXXX 100644
385
--- a/block/raw-format.c
386
+++ b/block/raw-format.c
387
@@ -XXX,XX +XXX,XX @@ static int raw_probe_geometry(BlockDriverState *bs, HDGeometry *geo)
388
}
389
390
static int coroutine_fn raw_co_copy_range_from(BlockDriverState *bs,
391
- BdrvChild *src, uint64_t src_offset,
392
- BdrvChild *dst, uint64_t dst_offset,
393
- uint64_t bytes, BdrvRequestFlags flags)
394
+ BdrvChild *src,
395
+ uint64_t src_offset,
396
+ BdrvChild *dst,
397
+ uint64_t dst_offset,
398
+ uint64_t bytes,
399
+ BdrvRequestFlags read_flags,
400
+ BdrvRequestFlags write_flags)
401
{
402
int ret;
403
404
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn raw_co_copy_range_from(BlockDriverState *bs,
405
return ret;
406
}
53
}
407
return bdrv_co_copy_range_from(bs->file, src_offset, dst, dst_offset,
54
diff --git a/tests/qemu-iotests/tests/qcow2-encryption b/tests/qemu-iotests/tests/qcow2-encryption
408
- bytes, flags);
55
new file mode 100755
409
+ bytes, read_flags, write_flags);
56
index XXXXXXX..XXXXXXX
410
}
57
--- /dev/null
411
58
+++ b/tests/qemu-iotests/tests/qcow2-encryption
412
static int coroutine_fn raw_co_copy_range_to(BlockDriverState *bs,
59
@@ -XXX,XX +XXX,XX @@
413
- BdrvChild *src, uint64_t src_offset,
60
+#!/usr/bin/env bash
414
- BdrvChild *dst, uint64_t dst_offset,
61
+# group: rw quick
415
- uint64_t bytes, BdrvRequestFlags flags)
62
+#
416
+ BdrvChild *src,
63
+# Test case for encryption support in qcow2
417
+ uint64_t src_offset,
64
+#
418
+ BdrvChild *dst,
65
+# Copyright (C) 2025 Red Hat, Inc.
419
+ uint64_t dst_offset,
66
+#
420
+ uint64_t bytes,
67
+# This program is free software; you can redistribute it and/or modify
421
+ BdrvRequestFlags read_flags,
68
+# it under the terms of the GNU General Public License as published by
422
+ BdrvRequestFlags write_flags)
69
+# the Free Software Foundation; either version 2 of the License, or
423
{
70
+# (at your option) any later version.
424
int ret;
71
+#
425
72
+# This program is distributed in the hope that it will be useful,
426
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn raw_co_copy_range_to(BlockDriverState *bs,
73
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
427
return ret;
74
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
428
}
75
+# GNU General Public License for more details.
429
return bdrv_co_copy_range_to(src, src_offset, bs->file, dst_offset, bytes,
76
+#
430
- flags);
77
+# You should have received a copy of the GNU General Public License
431
+ read_flags, write_flags);
78
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
432
}
79
+#
433
80
+
434
BlockDriver bdrv_raw = {
81
+# creator
435
diff --git a/qemu-img.c b/qemu-img.c
82
+owner=kwolf@redhat.com
436
index XXXXXXX..XXXXXXX 100644
83
+
437
--- a/qemu-img.c
84
+seq="$(basename $0)"
438
+++ b/qemu-img.c
85
+echo "QA output created by $seq"
439
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn convert_co_copy_range(ImgConvertState *s, int64_t sector
86
+
440
87
+status=1    # failure is the default!
441
ret = blk_co_copy_range(blk, offset, s->target,
88
+
442
sector_num << BDRV_SECTOR_BITS,
89
+_cleanup()
443
- n << BDRV_SECTOR_BITS, 0);
90
+{
444
+ n << BDRV_SECTOR_BITS, 0, 0);
91
+    _cleanup_test_img
445
if (ret < 0) {
92
+}
446
return ret;
93
+trap "_cleanup; exit \$status" 0 1 2 3 15
447
}
94
+
95
+# get standard environment, filters and checks
96
+. ../common.rc
97
+. ../common.filter
98
+
99
+# This tests qcow2-specific low-level functionality
100
+_supported_fmt qcow2
101
+_supported_proto file
102
+_require_working_luks
103
+
104
+IMG_SIZE=64M
105
+
106
+echo
107
+echo "=== Create an encrypted image ==="
108
+echo
109
+
110
+_make_test_img --object secret,id=sec0,data=123456 -o encrypt.format=luks,encrypt.key-secret=sec0 $IMG_SIZE
111
+$PYTHON ../qcow2.py "$TEST_IMG" dump-header-exts
112
+_img_info
113
+$QEMU_IMG check \
114
+ --object secret,id=sec0,data=123456 \
115
+ --image-opts file.filename="$TEST_IMG",encrypt.key-secret=sec0 \
116
+ | _filter_qemu_img_check
117
+
118
+echo
119
+echo "=== Remove the header extension ==="
120
+echo
121
+
122
+$PYTHON ../qcow2.py "$TEST_IMG" del-header-ext 0x0537be77
123
+$PYTHON ../qcow2.py "$TEST_IMG" dump-header-exts
124
+_img_info
125
+$QEMU_IMG check \
126
+ --object secret,id=sec0,data=123456 \
127
+ --image-opts file.filename="$TEST_IMG",encrypt.key-secret=sec0 2>&1 \
128
+ | _filter_qemu_img_check \
129
+ | _filter_testdir
130
+
131
+# success, all done
132
+echo "*** done"
133
+rm -f $seq.full
134
+status=0
135
diff --git a/tests/qemu-iotests/tests/qcow2-encryption.out b/tests/qemu-iotests/tests/qcow2-encryption.out
136
new file mode 100644
137
index XXXXXXX..XXXXXXX
138
--- /dev/null
139
+++ b/tests/qemu-iotests/tests/qcow2-encryption.out
140
@@ -XXX,XX +XXX,XX @@
141
+QA output created by qcow2-encryption
142
+
143
+=== Create an encrypted image ===
144
+
145
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
146
+Header extension:
147
+magic 0x537be77 (Crypto header)
148
+length 16
149
+data <binary>
150
+
151
+Header extension:
152
+magic 0x6803f857 (Feature table)
153
+length 384
154
+data <binary>
155
+
156
+image: TEST_DIR/t.IMGFMT
157
+file format: IMGFMT
158
+virtual size: 64 MiB (67108864 bytes)
159
+encrypted: yes
160
+cluster_size: 65536
161
+No errors were found on the image.
162
+
163
+=== Remove the header extension ===
164
+
165
+Header extension:
166
+magic 0x6803f857 (Feature table)
167
+length 384
168
+data <binary>
169
+
170
+qemu-img: Could not open 'TEST_DIR/t.IMGFMT': Missing CRYPTO header for crypt method 2
171
+qemu-img: Could not open 'file.filename=TEST_DIR/t.qcow2,encrypt.key-secret=sec0': Missing CRYPTO header for crypt method 2
172
+*** done
448
--
173
--
449
2.13.6
174
2.49.0
450
175
451
176
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
Serialized writes should be used in copy-on-write of backup(sync=none)
4
for image fleecing scheme.
5
6
We need to change an assert in bdrv_aligned_pwritev, added in
7
28de2dcd88de. The assert may fail now, because call to
8
wait_serialising_requests here may become first call to it for this
9
request with serializing flag set. It occurs if the request is aligned
10
(otherwise, we should already set serializing flag before calling
11
bdrv_aligned_pwritev and correspondingly waited for all intersecting
12
requests). However, for aligned requests, we should not care about
13
outdating of previously read data, as there no such data. Therefore,
14
let's just update an assert to not care about aligned requests.
15
16
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
17
Reviewed-by: Fam Zheng <famz@redhat.com>
18
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
19
---
20
include/block/block.h | 14 +++++++++++++-
21
block/io.c | 28 +++++++++++++++++++++++++++-
22
2 files changed, 40 insertions(+), 2 deletions(-)
23
24
diff --git a/include/block/block.h b/include/block/block.h
25
index XXXXXXX..XXXXXXX 100644
26
--- a/include/block/block.h
27
+++ b/include/block/block.h
28
@@ -XXX,XX +XXX,XX @@ typedef enum {
29
* content. */
30
BDRV_REQ_WRITE_UNCHANGED = 0x40,
31
32
+ /*
33
+ * BDRV_REQ_SERIALISING forces request serialisation for writes.
34
+ * It is used to ensure that writes to the backing file of a backup process
35
+ * target cannot race with a read of the backup target that defers to the
36
+ * backing file.
37
+ *
38
+ * Note, that BDRV_REQ_SERIALISING is _not_ opposite in meaning to
39
+ * BDRV_REQ_NO_SERIALISING. A more descriptive name for the latter might be
40
+ * _DO_NOT_WAIT_FOR_SERIALISING, except that is too long.
41
+ */
42
+ BDRV_REQ_SERIALISING = 0x80,
43
+
44
/* Mask of valid flags */
45
- BDRV_REQ_MASK = 0x7f,
46
+ BDRV_REQ_MASK = 0xff,
47
} BdrvRequestFlags;
48
49
typedef struct BlockSizes {
50
diff --git a/block/io.c b/block/io.c
51
index XXXXXXX..XXXXXXX 100644
52
--- a/block/io.c
53
+++ b/block/io.c
54
@@ -XXX,XX +XXX,XX @@ static void mark_request_serialising(BdrvTrackedRequest *req, uint64_t align)
55
req->overlap_bytes = MAX(req->overlap_bytes, overlap_bytes);
56
}
57
58
+static bool is_request_serialising_and_aligned(BdrvTrackedRequest *req)
59
+{
60
+ /*
61
+ * If the request is serialising, overlap_offset and overlap_bytes are set,
62
+ * so we can check if the request is aligned. Otherwise, don't care and
63
+ * return false.
64
+ */
65
+
66
+ return req->serialising && (req->offset == req->overlap_offset) &&
67
+ (req->bytes == req->overlap_bytes);
68
+}
69
+
70
/**
71
* Round a region to cluster boundaries
72
*/
73
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_aligned_preadv(BdrvChild *child,
74
mark_request_serialising(req, bdrv_get_cluster_size(bs));
75
}
76
77
+ /* BDRV_REQ_SERIALISING is only for write operation */
78
+ assert(!(flags & BDRV_REQ_SERIALISING));
79
+
80
if (!(flags & BDRV_REQ_NO_SERIALISING)) {
81
wait_serialising_requests(req);
82
}
83
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_aligned_pwritev(BdrvChild *child,
84
85
/* BDRV_REQ_NO_SERIALISING is only for read operation */
86
assert(!(flags & BDRV_REQ_NO_SERIALISING));
87
+
88
+ if (flags & BDRV_REQ_SERIALISING) {
89
+ mark_request_serialising(req, bdrv_get_cluster_size(bs));
90
+ }
91
+
92
waited = wait_serialising_requests(req);
93
- assert(!waited || !req->serialising);
94
+ assert(!waited || !req->serialising ||
95
+ is_request_serialising_and_aligned(req));
96
assert(req->overlap_offset <= offset);
97
assert(offset + bytes <= req->overlap_offset + req->overlap_bytes);
98
if (flags & BDRV_REQ_WRITE_UNCHANGED) {
99
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_co_copy_range_internal(
100
tracked_request_begin(&req, src->bs, src_offset, bytes,
101
BDRV_TRACKED_READ);
102
103
+ /* BDRV_REQ_SERIALISING is only for write operation */
104
+ assert(!(read_flags & BDRV_REQ_SERIALISING));
105
if (!(read_flags & BDRV_REQ_NO_SERIALISING)) {
106
wait_serialising_requests(&req);
107
}
108
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_co_copy_range_internal(
109
110
/* BDRV_REQ_NO_SERIALISING is only for read operation */
111
assert(!(write_flags & BDRV_REQ_NO_SERIALISING));
112
+ if (write_flags & BDRV_REQ_SERIALISING) {
113
+ mark_request_serialising(&req, bdrv_get_cluster_size(dst->bs));
114
+ }
115
wait_serialising_requests(&req);
116
117
ret = dst->bs->drv->bdrv_co_copy_range_to(dst->bs,
118
--
119
2.13.6
120
121
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
Fleecing scheme works as follows: we want a kind of temporary snapshot
4
of active drive A. We create temporary image B, with B->backing = A.
5
Then we start backup(sync=none) from A to B. From this point, B reads
6
as point-in-time snapshot of A (A continues to be active drive,
7
accepting guest IO).
8
9
This scheme needs some additional synchronization between reads from B
10
and backup COW operations, otherwise, the following situation is
11
theoretically possible:
12
13
(assume B is qcow2, client is NBD client, reading from B)
14
15
1. client starts reading and take qcow2 mutex in qcow2_co_preadv, and
16
goes up to l2 table loading (assume cache miss)
17
18
2) guest write => backup COW => qcow2 write =>
19
try to take qcow2 mutex => waiting
20
21
3. l2 table loaded, we see that cluster is UNALLOCATED, go to
22
"case QCOW2_CLUSTER_UNALLOCATED" and unlock mutex before
23
bdrv_co_preadv(bs->backing, ...)
24
25
4) aha, mutex unlocked, backup COW continues, and we finally finish
26
guest write and change cluster in our active disk A
27
28
5. actually, do bdrv_co_preadv(bs->backing, ...) and read
29
_new updated_ data.
30
31
To avoid this, let's make backup writes serializing, to not intersect
32
with reads from B.
33
34
Note: we expand range of handled cases from (sync=none and
35
B->backing = A) to just (A in backing chain of B), to finally allow
36
safe reading from B during backup for all cases when A in backing chain
37
of B, i.e. B formally looks like point-in-time snapshot of A.
38
39
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
40
Reviewed-by: Fam Zheng <famz@redhat.com>
41
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
42
---
43
block/backup.c | 20 ++++++++++++++------
44
1 file changed, 14 insertions(+), 6 deletions(-)
45
46
diff --git a/block/backup.c b/block/backup.c
47
index XXXXXXX..XXXXXXX 100644
48
--- a/block/backup.c
49
+++ b/block/backup.c
50
@@ -XXX,XX +XXX,XX @@ typedef struct BackupBlockJob {
51
HBitmap *copy_bitmap;
52
bool use_copy_range;
53
int64_t copy_range_size;
54
+
55
+ bool serialize_target_writes;
56
} BackupBlockJob;
57
58
static const BlockJobDriver backup_job_driver;
59
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn backup_cow_with_bounce_buffer(BackupBlockJob *job,
60
QEMUIOVector qiov;
61
BlockBackend *blk = job->common.blk;
62
int nbytes;
63
+ int read_flags = is_write_notifier ? BDRV_REQ_NO_SERIALISING : 0;
64
+ int write_flags = job->serialize_target_writes ? BDRV_REQ_SERIALISING : 0;
65
66
hbitmap_reset(job->copy_bitmap, start / job->cluster_size, 1);
67
nbytes = MIN(job->cluster_size, job->len - start);
68
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn backup_cow_with_bounce_buffer(BackupBlockJob *job,
69
iov.iov_len = nbytes;
70
qemu_iovec_init_external(&qiov, &iov, 1);
71
72
- ret = blk_co_preadv(blk, start, qiov.size, &qiov,
73
- is_write_notifier ? BDRV_REQ_NO_SERIALISING : 0);
74
+ ret = blk_co_preadv(blk, start, qiov.size, &qiov, read_flags);
75
if (ret < 0) {
76
trace_backup_do_cow_read_fail(job, start, ret);
77
if (error_is_read) {
78
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn backup_cow_with_bounce_buffer(BackupBlockJob *job,
79
80
if (qemu_iovec_is_zero(&qiov)) {
81
ret = blk_co_pwrite_zeroes(job->target, start,
82
- qiov.size, BDRV_REQ_MAY_UNMAP);
83
+ qiov.size, write_flags | BDRV_REQ_MAY_UNMAP);
84
} else {
85
ret = blk_co_pwritev(job->target, start,
86
- qiov.size, &qiov,
87
- job->compress ? BDRV_REQ_WRITE_COMPRESSED : 0);
88
+ qiov.size, &qiov, write_flags |
89
+ (job->compress ? BDRV_REQ_WRITE_COMPRESSED : 0));
90
}
91
if (ret < 0) {
92
trace_backup_do_cow_write_fail(job, start, ret);
93
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn backup_cow_with_offload(BackupBlockJob *job,
94
int nr_clusters;
95
BlockBackend *blk = job->common.blk;
96
int nbytes;
97
+ int read_flags = is_write_notifier ? BDRV_REQ_NO_SERIALISING : 0;
98
+ int write_flags = job->serialize_target_writes ? BDRV_REQ_SERIALISING : 0;
99
100
assert(QEMU_IS_ALIGNED(job->copy_range_size, job->cluster_size));
101
nbytes = MIN(job->copy_range_size, end - start);
102
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn backup_cow_with_offload(BackupBlockJob *job,
103
hbitmap_reset(job->copy_bitmap, start / job->cluster_size,
104
nr_clusters);
105
ret = blk_co_copy_range(blk, start, job->target, start, nbytes,
106
- is_write_notifier ? BDRV_REQ_NO_SERIALISING : 0, 0);
107
+ read_flags, write_flags);
108
if (ret < 0) {
109
trace_backup_do_cow_copy_range_fail(job, start, ret);
110
hbitmap_set(job->copy_bitmap, start / job->cluster_size,
111
@@ -XXX,XX +XXX,XX @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
112
sync_bitmap : NULL;
113
job->compress = compress;
114
115
+ /* Detect image-fleecing (and similar) schemes */
116
+ job->serialize_target_writes = bdrv_chain_contains(target, bs);
117
+
118
/* If there is no backing file on the target, we cannot rely on COW if our
119
* backup cluster size is smaller than the target cluster size. Even for
120
* targets with a backing file, try to avoid COW if possible. */
121
--
122
2.13.6
123
124
diff view generated by jsdifflib
Deleted patch
1
From: Ari Sundholm <ari@tuxera.com>
2
1
3
This was accidentally omitted. Thanks to Eric Blake for spotting this.
4
5
Signed-off-by: Ari Sundholm <ari@tuxera.com>
6
Reviewed-by: Eric Blake <eblake@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
---
9
qapi/block-core.json | 2 ++
10
1 file changed, 2 insertions(+)
11
12
diff --git a/qapi/block-core.json b/qapi/block-core.json
13
index XXXXXXX..XXXXXXX 100644
14
--- a/qapi/block-core.json
15
+++ b/qapi/block-core.json
16
@@ -XXX,XX +XXX,XX @@
17
# @log-sector-size: sector size used in logging writes to @file, determines
18
# granularity of offsets and sizes of writes (default: 512)
19
#
20
+# @log-append: append to an existing log (default: false)
21
+#
22
# @log-super-update-interval: interval of write requests after which the log
23
# super block is updated to disk (default: 4096)
24
#
25
--
26
2.13.6
27
28
diff view generated by jsdifflib
Deleted patch
1
From: Ari Sundholm <ari@tuxera.com>
2
1
3
The sector size needs to be large enough to accommodate the data
4
structures for the log super block and log write entries. This was
5
previously not properly checked, which made it possible to cause
6
QEMU to badly misbehave.
7
8
Signed-off-by: Ari Sundholm <ari@tuxera.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
11
block/blklogwrites.c | 5 ++++-
12
1 file changed, 4 insertions(+), 1 deletion(-)
13
14
diff --git a/block/blklogwrites.c b/block/blklogwrites.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/block/blklogwrites.c
17
+++ b/block/blklogwrites.c
18
@@ -XXX,XX +XXX,XX @@ static inline uint32_t blk_log_writes_log2(uint32_t value)
19
20
static inline bool blk_log_writes_sector_size_valid(uint32_t sector_size)
21
{
22
- return sector_size < (1ull << 24) && is_power_of_2(sector_size);
23
+ return is_power_of_2(sector_size) &&
24
+ sector_size >= sizeof(struct log_write_super) &&
25
+ sector_size >= sizeof(struct log_write_entry) &&
26
+ sector_size < (1ull << 24);
27
}
28
29
static uint64_t blk_log_writes_find_cur_log_sector(BdrvChild *log,
30
--
31
2.13.6
32
33
diff view generated by jsdifflib
Deleted patch
1
From: Cornelia Huck <cohuck@redhat.com>
2
1
3
This reverts commit 6266e900b8083945cb766b45c124fb3c42932cb3.
4
5
Some deprecated -drive options were still in use by libvirt, only
6
fixed with libvirt commit b340c6c614 ("qemu: format serial and geometry
7
on frontend disk device"), which is not yet in any released version
8
of libvirt.
9
10
So let's hold off removing the deprecated options for one more QEMU
11
release.
12
13
Reported-by: Christian Borntraeger <borntraeger@de.ibm.com>
14
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
15
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
16
---
17
blockdev.c | 12 ++++++++++++
18
1 file changed, 12 insertions(+)
19
20
diff --git a/blockdev.c b/blockdev.c
21
index XXXXXXX..XXXXXXX 100644
22
--- a/blockdev.c
23
+++ b/blockdev.c
24
@@ -XXX,XX +XXX,XX @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type)
25
const char *filename;
26
Error *local_err = NULL;
27
int i;
28
+ const char *deprecated[] = {
29
+ };
30
31
/* Change legacy command line options into QMP ones */
32
static const struct {
33
@@ -XXX,XX +XXX,XX @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type)
34
goto fail;
35
}
36
37
+ /* Other deprecated options */
38
+ if (!qtest_enabled()) {
39
+ for (i = 0; i < ARRAY_SIZE(deprecated); i++) {
40
+ if (qemu_opt_get(legacy_opts, deprecated[i]) != NULL) {
41
+ error_report("'%s' is deprecated, please use the corresponding "
42
+ "option of '-device' instead", deprecated[i]);
43
+ }
44
+ }
45
+ }
46
+
47
/* Media type */
48
value = qemu_opt_get(legacy_opts, "media");
49
if (value) {
50
--
51
2.13.6
52
53
diff view generated by jsdifflib
1
From: Fam Zheng <famz@redhat.com>
1
Originally, all failed SG_IO requests called scsi_handle_rw_error() to
2
apply the configured error policy. However, commit f3126d65, which was
3
supposed to be a mere refactoring for scsi-disk.c, broke this and
4
accidentally completed the SCSI request without considering the error
5
policy any more if the error was signalled in the host_status field.
2
6
3
Other I/O functions are already using a BdrvChild pointer in the API, so
7
Apart from the commit message not describing the change as intended,
4
make discard do the same. It makes it possible to initiate the same
8
errors indicated in host_status are also obviously backend errors and
5
permission checks before doing I/O, and much easier to share the
9
not something the guest must deal with independently of the error
6
helper functions for this, which will be added and used by write,
10
policy.
7
truncate and copy range paths.
8
11
9
Signed-off-by: Fam Zheng <famz@redhat.com>
12
This behaviour means that some recoverable errors (such as a path error
13
in multipath configurations) were reported to the guest anyway, which
14
might not expect it and might consider its disk broken.
15
16
Make sure that we apply the error policy again for host_status errors,
17
too. This addresses an existing FIXME comment and allows us to remove
18
some comments warning that callbacks weren't always called. With this
19
fix, they are called in all cases again.
20
21
The return value passed to the request callback doesn't have more free
22
values that could be used to indicate host_status errors as well as SAM
23
status codes and negative errno. Store the value in the host_status
24
field of the SCSIRequest instead and use -ENODEV as the return value (if
25
a path hasn't been reachable for a while, blk_aio_ioctl() will return
26
-ENODEV instead of just setting host_status, so just reuse it here -
27
it's not necessarily entirely accurate, but it's as good as any errno).
28
29
Cc: qemu-stable@nongnu.org
30
Fixes: f3126d65b393 ('scsi: move host_status handling into SCSI drivers')
31
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
32
Message-ID: <20250407155949.44736-1-kwolf@redhat.com>
33
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
34
Reviewed-by: Hanna Czenczek <hreitz@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
35
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
---
36
---
12
include/block/block.h | 4 ++--
37
hw/scsi/scsi-disk.c | 39 +++++++++++++++++++++++++--------------
13
block/blkdebug.c | 2 +-
38
1 file changed, 25 insertions(+), 14 deletions(-)
14
block/blklogwrites.c | 2 +-
15
block/blkreplay.c | 2 +-
16
block/block-backend.c | 2 +-
17
block/copy-on-read.c | 2 +-
18
block/io.c | 18 +++++++++---------
19
block/mirror.c | 2 +-
20
block/qcow2-refcount.c | 2 +-
21
block/raw-format.c | 2 +-
22
block/throttle.c | 2 +-
23
11 files changed, 20 insertions(+), 20 deletions(-)
24
39
25
diff --git a/include/block/block.h b/include/block/block.h
40
diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c
26
index XXXXXXX..XXXXXXX 100644
41
index XXXXXXX..XXXXXXX 100644
27
--- a/include/block/block.h
42
--- a/hw/scsi/scsi-disk.c
28
+++ b/include/block/block.h
43
+++ b/hw/scsi/scsi-disk.c
29
@@ -XXX,XX +XXX,XX @@ AioWait *bdrv_get_aio_wait(BlockDriverState *bs);
44
@@ -XXX,XX +XXX,XX @@ struct SCSIDiskClass {
30
bdrv_get_aio_context(bs_), \
45
SCSIDeviceClass parent_class;
31
cond); })
46
/*
32
47
* Callbacks receive ret == 0 for success. Errors are represented either as
33
-int bdrv_pdiscard(BlockDriverState *bs, int64_t offset, int bytes);
48
- * negative errno values, or as positive SAM status codes.
34
-int bdrv_co_pdiscard(BlockDriverState *bs, int64_t offset, int bytes);
49
- *
35
+int bdrv_pdiscard(BdrvChild *child, int64_t offset, int bytes);
50
- * Beware: For errors returned in host_status, the function may directly
36
+int bdrv_co_pdiscard(BdrvChild *child, int64_t offset, int bytes);
51
- * complete the request and never call the callback.
37
int bdrv_has_zero_init_1(BlockDriverState *bs);
52
+ * negative errno values, or as positive SAM status codes. For host_status
38
int bdrv_has_zero_init(BlockDriverState *bs);
53
+ * errors, the function passes ret == -ENODEV and sets the host_status field
39
bool bdrv_unallocated_blocks_are_zero(BlockDriverState *bs);
54
+ * of the SCSIRequest.
40
diff --git a/block/blkdebug.c b/block/blkdebug.c
55
*/
41
index XXXXXXX..XXXXXXX 100644
56
DMAIOFunc *dma_readv;
42
--- a/block/blkdebug.c
57
DMAIOFunc *dma_writev;
43
+++ b/block/blkdebug.c
58
@@ -XXX,XX +XXX,XX @@ static bool scsi_handle_rw_error(SCSIDiskReq *r, int ret, bool acct_failed)
44
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn blkdebug_co_pdiscard(BlockDriverState *bs,
59
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
45
return err;
60
SCSIDiskClass *sdc = (SCSIDiskClass *) object_get_class(OBJECT(s));
46
}
61
SCSISense sense = SENSE_CODE(NO_SENSE);
47
62
+ int16_t host_status;
48
- return bdrv_co_pdiscard(bs->file->bs, offset, bytes);
63
int error;
49
+ return bdrv_co_pdiscard(bs->file, offset, bytes);
64
bool req_has_sense = false;
65
BlockErrorAction action;
66
int status;
67
68
+ /*
69
+ * host_status should only be set for SG_IO requests that came back with a
70
+ * host_status error in scsi_block_sgio_complete(). This error path passes
71
+ * -ENODEV as the return value.
72
+ *
73
+ * Reset host_status in the request because we may still want to complete
74
+ * the request successfully with the 'stop' or 'ignore' error policy.
75
+ */
76
+ host_status = r->req.host_status;
77
+ if (host_status != -1) {
78
+ assert(ret == -ENODEV);
79
+ r->req.host_status = -1;
80
+ }
81
+
82
if (ret < 0) {
83
status = scsi_sense_from_errno(-ret, &sense);
84
error = -ret;
85
@@ -XXX,XX +XXX,XX @@ static bool scsi_handle_rw_error(SCSIDiskReq *r, int ret, bool acct_failed)
86
if (acct_failed) {
87
block_acct_failed(blk_get_stats(s->qdev.conf.blk), &r->acct);
88
}
89
+ if (host_status != -1) {
90
+ scsi_req_complete_failed(&r->req, host_status);
91
+ return true;
92
+ }
93
if (req_has_sense) {
94
sdc->update_sense(&r->req);
95
} else if (status == CHECK_CONDITION) {
96
@@ -XXX,XX +XXX,XX @@ done:
97
scsi_req_unref(&r->req);
50
}
98
}
51
99
52
static int coroutine_fn blkdebug_co_block_status(BlockDriverState *bs,
100
-/* May not be called in all error cases, don't rely on cleanup here */
53
diff --git a/block/blklogwrites.c b/block/blklogwrites.c
101
static void scsi_dma_complete(void *opaque, int ret)
54
index XXXXXXX..XXXXXXX 100644
55
--- a/block/blklogwrites.c
56
+++ b/block/blklogwrites.c
57
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn blk_log_writes_co_do_file_flush(BlkLogWritesFileReq *fr)
58
static int coroutine_fn
59
blk_log_writes_co_do_file_pdiscard(BlkLogWritesFileReq *fr)
60
{
102
{
61
- return bdrv_co_pdiscard(fr->bs->file->bs, fr->offset, fr->bytes);
103
SCSIDiskReq *r = (SCSIDiskReq *)opaque;
62
+ return bdrv_co_pdiscard(fr->bs->file, fr->offset, fr->bytes);
104
@@ -XXX,XX +XXX,XX @@ done:
105
scsi_req_unref(&r->req);
63
}
106
}
64
107
65
static int coroutine_fn
108
-/* May not be called in all error cases, don't rely on cleanup here */
66
diff --git a/block/blkreplay.c b/block/blkreplay.c
109
static void scsi_read_complete(void *opaque, int ret)
67
index XXXXXXX..XXXXXXX 100755
68
--- a/block/blkreplay.c
69
+++ b/block/blkreplay.c
70
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn blkreplay_co_pdiscard(BlockDriverState *bs,
71
int64_t offset, int bytes)
72
{
110
{
73
uint64_t reqid = blkreplay_next_id();
111
SCSIDiskReq *r = (SCSIDiskReq *)opaque;
74
- int ret = bdrv_co_pdiscard(bs->file->bs, offset, bytes);
112
@@ -XXX,XX +XXX,XX @@ done:
75
+ int ret = bdrv_co_pdiscard(bs->file, offset, bytes);
113
scsi_req_unref(&r->req);
76
block_request_create(reqid, bs, qemu_coroutine_self());
77
qemu_coroutine_yield();
78
79
diff --git a/block/block-backend.c b/block/block-backend.c
80
index XXXXXXX..XXXXXXX 100644
81
--- a/block/block-backend.c
82
+++ b/block/block-backend.c
83
@@ -XXX,XX +XXX,XX @@ int blk_co_pdiscard(BlockBackend *blk, int64_t offset, int bytes)
84
return ret;
85
}
86
87
- return bdrv_co_pdiscard(blk_bs(blk), offset, bytes);
88
+ return bdrv_co_pdiscard(blk->root, offset, bytes);
89
}
114
}
90
115
91
int blk_co_flush(BlockBackend *blk)
116
-/* May not be called in all error cases, don't rely on cleanup here */
92
diff --git a/block/copy-on-read.c b/block/copy-on-read.c
117
static void scsi_write_complete(void * opaque, int ret)
93
index XXXXXXX..XXXXXXX 100644
94
--- a/block/copy-on-read.c
95
+++ b/block/copy-on-read.c
96
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn cor_co_pwrite_zeroes(BlockDriverState *bs,
97
static int coroutine_fn cor_co_pdiscard(BlockDriverState *bs,
98
int64_t offset, int bytes)
99
{
118
{
100
- return bdrv_co_pdiscard(bs->file->bs, offset, bytes);
119
SCSIDiskReq *r = (SCSIDiskReq *)opaque;
101
+ return bdrv_co_pdiscard(bs->file, offset, bytes);
120
@@ -XXX,XX +XXX,XX @@ static void scsi_block_sgio_complete(void *opaque, int ret)
102
}
121
sg_io_hdr_t *io_hdr = &req->io_header;
103
122
104
123
if (ret == 0) {
105
diff --git a/block/io.c b/block/io.c
124
- /* FIXME This skips calling req->cb() and any cleanup in it */
106
index XXXXXXX..XXXXXXX 100644
125
if (io_hdr->host_status != SCSI_HOST_OK) {
107
--- a/block/io.c
126
- scsi_req_complete_failed(&r->req, io_hdr->host_status);
108
+++ b/block/io.c
127
- scsi_req_unref(&r->req);
109
@@ -XXX,XX +XXX,XX @@ int bdrv_flush(BlockDriverState *bs)
128
- return;
110
}
129
- }
111
130
-
112
typedef struct DiscardCo {
131
- if (io_hdr->driver_status & SG_ERR_DRIVER_TIMEOUT) {
113
- BlockDriverState *bs;
132
+ r->req.host_status = io_hdr->host_status;
114
+ BdrvChild *child;
133
+ ret = -ENODEV;
115
int64_t offset;
134
+ } else if (io_hdr->driver_status & SG_ERR_DRIVER_TIMEOUT) {
116
int bytes;
135
ret = BUSY;
117
int ret;
136
} else {
118
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn bdrv_pdiscard_co_entry(void *opaque)
137
ret = io_hdr->status;
119
{
120
DiscardCo *rwco = opaque;
121
122
- rwco->ret = bdrv_co_pdiscard(rwco->bs, rwco->offset, rwco->bytes);
123
+ rwco->ret = bdrv_co_pdiscard(rwco->child, rwco->offset, rwco->bytes);
124
}
125
126
-int coroutine_fn bdrv_co_pdiscard(BlockDriverState *bs, int64_t offset,
127
- int bytes)
128
+int coroutine_fn bdrv_co_pdiscard(BdrvChild *child, int64_t offset, int bytes)
129
{
130
BdrvTrackedRequest req;
131
int max_pdiscard, ret;
132
int head, tail, align;
133
+ BlockDriverState *bs = child->bs;
134
135
- if (!bs->drv) {
136
+ if (!bs || !bs->drv) {
137
return -ENOMEDIUM;
138
}
139
140
@@ -XXX,XX +XXX,XX @@ out:
141
return ret;
142
}
143
144
-int bdrv_pdiscard(BlockDriverState *bs, int64_t offset, int bytes)
145
+int bdrv_pdiscard(BdrvChild *child, int64_t offset, int bytes)
146
{
147
Coroutine *co;
148
DiscardCo rwco = {
149
- .bs = bs,
150
+ .child = child,
151
.offset = offset,
152
.bytes = bytes,
153
.ret = NOT_DONE,
154
@@ -XXX,XX +XXX,XX @@ int bdrv_pdiscard(BlockDriverState *bs, int64_t offset, int bytes)
155
bdrv_pdiscard_co_entry(&rwco);
156
} else {
157
co = qemu_coroutine_create(bdrv_pdiscard_co_entry, &rwco);
158
- bdrv_coroutine_enter(bs, co);
159
- BDRV_POLL_WHILE(bs, rwco.ret == NOT_DONE);
160
+ bdrv_coroutine_enter(child->bs, co);
161
+ BDRV_POLL_WHILE(child->bs, rwco.ret == NOT_DONE);
162
}
163
164
return rwco.ret;
165
diff --git a/block/mirror.c b/block/mirror.c
166
index XXXXXXX..XXXXXXX 100644
167
--- a/block/mirror.c
168
+++ b/block/mirror.c
169
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_mirror_top_do_write(BlockDriverState *bs,
170
break;
171
172
case MIRROR_METHOD_DISCARD:
173
- ret = bdrv_co_pdiscard(bs->backing->bs, offset, bytes);
174
+ ret = bdrv_co_pdiscard(bs->backing, offset, bytes);
175
break;
176
177
default:
178
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
179
index XXXXXXX..XXXXXXX 100644
180
--- a/block/qcow2-refcount.c
181
+++ b/block/qcow2-refcount.c
182
@@ -XXX,XX +XXX,XX @@ void qcow2_process_discards(BlockDriverState *bs, int ret)
183
184
/* Discard is optional, ignore the return value */
185
if (ret >= 0) {
186
- bdrv_pdiscard(bs->file->bs, d->offset, d->bytes);
187
+ bdrv_pdiscard(bs->file, d->offset, d->bytes);
188
}
189
190
g_free(d);
191
diff --git a/block/raw-format.c b/block/raw-format.c
192
index XXXXXXX..XXXXXXX 100644
193
--- a/block/raw-format.c
194
+++ b/block/raw-format.c
195
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn raw_co_pdiscard(BlockDriverState *bs,
196
if (ret) {
197
return ret;
198
}
199
- return bdrv_co_pdiscard(bs->file->bs, offset, bytes);
200
+ return bdrv_co_pdiscard(bs->file, offset, bytes);
201
}
202
203
static int64_t raw_getlength(BlockDriverState *bs)
204
diff --git a/block/throttle.c b/block/throttle.c
205
index XXXXXXX..XXXXXXX 100644
206
--- a/block/throttle.c
207
+++ b/block/throttle.c
208
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn throttle_co_pdiscard(BlockDriverState *bs,
209
ThrottleGroupMember *tgm = bs->opaque;
210
throttle_group_co_io_limits_intercept(tgm, bytes, true);
211
212
- return bdrv_co_pdiscard(bs->file->bs, offset, bytes);
213
+ return bdrv_co_pdiscard(bs->file, offset, bytes);
214
}
215
216
static int throttle_co_flush(BlockDriverState *bs)
217
--
138
--
218
2.13.6
139
2.49.0
219
220
diff view generated by jsdifflib
1
From: Cornelia Huck <cohuck@redhat.com>
1
From: Vitalii Mordan <mordan@ispras.ru>
2
2
3
This reverts commit b0083267444a5e0f28391f6c2831a539f878d424.
3
This patch addresses potential data races involving access to Job fields
4
in the test-bdrv-drain test.
4
5
5
Hold off removing this for one more QEMU release (current libvirt
6
Fixes: 7253220de4 ("test-bdrv-drain: Test drain vs. block jobs")
6
release still uses it.)
7
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2900
7
8
Signed-off-by: Vitalii Mordan <mordan@ispras.ru>
8
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
9
Message-ID: <20250402102119.3345626-1-mordan@ispras.ru>
10
[kwolf: Fixed up coding style and one missing atomic access]
11
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
13
---
11
include/hw/block/block.h | 1 +
14
include/qemu/job.h | 3 +++
12
include/sysemu/blockdev.h | 1 +
15
job.c | 6 ++++++
13
block/block-backend.c | 1 +
16
tests/unit/test-bdrv-drain.c | 32 +++++++++++++++++++-------------
14
blockdev.c | 10 ++++++++++
17
3 files changed, 28 insertions(+), 13 deletions(-)
15
hw/block/block.c | 13 +++++++++++++
16
hw/block/nvme.c | 1 +
17
hw/block/virtio-blk.c | 1 +
18
hw/ide/qdev.c | 1 +
19
hw/scsi/scsi-disk.c | 1 +
20
hw/usb/dev-storage.c | 1 +
21
tests/ahci-test.c | 6 +++---
22
tests/ide-test.c | 8 ++++----
23
qemu-doc.texi | 5 +++++
24
qemu-options.hx | 6 +++++-
25
14 files changed, 48 insertions(+), 8 deletions(-)
26
18
27
diff --git a/include/hw/block/block.h b/include/hw/block/block.h
19
diff --git a/include/qemu/job.h b/include/qemu/job.h
28
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
29
--- a/include/hw/block/block.h
21
--- a/include/qemu/job.h
30
+++ b/include/hw/block/block.h
22
+++ b/include/qemu/job.h
31
@@ -XXX,XX +XXX,XX @@ static inline unsigned int get_physical_block_exp(BlockConf *conf)
23
@@ -XXX,XX +XXX,XX @@ bool job_is_ready(Job *job);
32
24
/* Same as job_is_ready(), but called with job lock held. */
33
/* Configuration helpers */
25
bool job_is_ready_locked(Job *job);
34
26
35
+void blkconf_serial(BlockConf *conf, char **serial);
27
+/** Returns whether the job is paused. Called with job_mutex *not* held. */
36
bool blkconf_geometry(BlockConf *conf, int *trans,
28
+bool job_is_paused(Job *job);
37
unsigned cyls_max, unsigned heads_max, unsigned secs_max,
29
+
38
Error **errp);
30
/**
39
diff --git a/include/sysemu/blockdev.h b/include/sysemu/blockdev.h
31
* Request @job to pause at the next pause point. Must be paired with
32
* job_resume(). If the job is supposed to be resumed by user action, call
33
diff --git a/job.c b/job.c
40
index XXXXXXX..XXXXXXX 100644
34
index XXXXXXX..XXXXXXX 100644
41
--- a/include/sysemu/blockdev.h
35
--- a/job.c
42
+++ b/include/sysemu/blockdev.h
36
+++ b/job.c
43
@@ -XXX,XX +XXX,XX @@ struct DriveInfo {
37
@@ -XXX,XX +XXX,XX @@ bool job_is_cancelled_locked(Job *job)
44
bool is_default; /* Added by default_drive() ? */
38
return job->force_cancel;
45
int media_cd;
46
QemuOpts *opts;
47
+ char *serial;
48
QTAILQ_ENTRY(DriveInfo) next;
49
};
50
51
diff --git a/block/block-backend.c b/block/block-backend.c
52
index XXXXXXX..XXXXXXX 100644
53
--- a/block/block-backend.c
54
+++ b/block/block-backend.c
55
@@ -XXX,XX +XXX,XX @@ static void drive_info_del(DriveInfo *dinfo)
56
return;
57
}
58
qemu_opts_del(dinfo->opts);
59
+ g_free(dinfo->serial);
60
g_free(dinfo);
61
}
39
}
62
40
63
diff --git a/blockdev.c b/blockdev.c
41
+bool job_is_paused(Job *job)
64
index XXXXXXX..XXXXXXX 100644
65
--- a/blockdev.c
66
+++ b/blockdev.c
67
@@ -XXX,XX +XXX,XX @@ QemuOptsList qemu_legacy_drive_opts = {
68
.type = QEMU_OPT_STRING,
69
.help = "interface (ide, scsi, sd, mtd, floppy, pflash, virtio)",
70
},{
71
+ .name = "serial",
72
+ .type = QEMU_OPT_STRING,
73
+ .help = "disk serial number",
74
+ },{
75
.name = "file",
76
.type = QEMU_OPT_STRING,
77
.help = "file name",
78
@@ -XXX,XX +XXX,XX @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type)
79
const char *werror, *rerror;
80
bool read_only = false;
81
bool copy_on_read;
82
+ const char *serial;
83
const char *filename;
84
Error *local_err = NULL;
85
int i;
86
const char *deprecated[] = {
87
+ "serial"
88
};
89
90
/* Change legacy command line options into QMP ones */
91
@@ -XXX,XX +XXX,XX @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type)
92
goto fail;
93
}
94
95
+ /* Serial number */
96
+ serial = qemu_opt_get(legacy_opts, "serial");
97
+
98
/* no id supplied -> create one */
99
if (qemu_opts_id(all_opts) == NULL) {
100
char *new_id;
101
@@ -XXX,XX +XXX,XX @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type)
102
dinfo->type = type;
103
dinfo->bus = bus_id;
104
dinfo->unit = unit_id;
105
+ dinfo->serial = g_strdup(serial);
106
107
blk_set_legacy_dinfo(blk, dinfo);
108
109
diff --git a/hw/block/block.c b/hw/block/block.c
110
index XXXXXXX..XXXXXXX 100644
111
--- a/hw/block/block.c
112
+++ b/hw/block/block.c
113
@@ -XXX,XX +XXX,XX @@
114
#include "qapi/qapi-types-block.h"
115
#include "qemu/error-report.h"
116
117
+void blkconf_serial(BlockConf *conf, char **serial)
118
+{
42
+{
119
+ DriveInfo *dinfo;
43
+ JOB_LOCK_GUARD();
120
+
44
+ return job->paused;
121
+ if (!*serial) {
122
+ /* try to fall back to value set with legacy -drive serial=... */
123
+ dinfo = blk_legacy_dinfo(conf->blk);
124
+ if (dinfo) {
125
+ *serial = g_strdup(dinfo->serial);
126
+ }
127
+ }
128
+}
45
+}
129
+
46
+
130
void blkconf_blocksizes(BlockConf *conf)
47
bool job_is_cancelled(Job *job)
131
{
48
{
132
BlockBackend *blk = conf->blk;
49
JOB_LOCK_GUARD();
133
diff --git a/hw/block/nvme.c b/hw/block/nvme.c
50
diff --git a/tests/unit/test-bdrv-drain.c b/tests/unit/test-bdrv-drain.c
134
index XXXXXXX..XXXXXXX 100644
51
index XXXXXXX..XXXXXXX 100644
135
--- a/hw/block/nvme.c
52
--- a/tests/unit/test-bdrv-drain.c
136
+++ b/hw/block/nvme.c
53
+++ b/tests/unit/test-bdrv-drain.c
137
@@ -XXX,XX +XXX,XX @@ static void nvme_realize(PCIDevice *pci_dev, Error **errp)
54
@@ -XXX,XX +XXX,XX @@ typedef struct TestBlockJob {
138
return;
55
BlockDriverState *bs;
56
int run_ret;
57
int prepare_ret;
58
+
59
+ /* Accessed with atomics */
60
bool running;
61
bool should_complete;
62
} TestBlockJob;
63
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn test_job_run(Job *job, Error **errp)
64
65
/* We are running the actual job code past the pause point in
66
* job_co_entry(). */
67
- s->running = true;
68
+ qatomic_set(&s->running, true);
69
70
job_transition_to_ready(&s->common.job);
71
- while (!s->should_complete) {
72
+ while (!qatomic_read(&s->should_complete)) {
73
/* Avoid job_sleep_ns() because it marks the job as !busy. We want to
74
* emulate some actual activity (probably some I/O) here so that drain
75
* has to wait for this activity to stop. */
76
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn test_job_run(Job *job, Error **errp)
77
static void test_job_complete(Job *job, Error **errp)
78
{
79
TestBlockJob *s = container_of(job, TestBlockJob, common.job);
80
- s->should_complete = true;
81
+ qatomic_set(&s->should_complete, true);
82
}
83
84
BlockJobDriver test_job_driver = {
85
@@ -XXX,XX +XXX,XX @@ static void test_blockjob_common_drain_node(enum drain_type drain_type,
86
/* job_co_entry() is run in the I/O thread, wait for the actual job
87
* code to start (we don't want to catch the job in the pause point in
88
* job_co_entry(). */
89
- while (!tjob->running) {
90
+ while (!qatomic_read(&tjob->running)) {
91
aio_poll(qemu_get_aio_context(), false);
92
}
139
}
93
}
140
94
@@ -XXX,XX +XXX,XX @@ static void test_blockjob_common_drain_node(enum drain_type drain_type,
141
+ blkconf_serial(&n->conf, &n->serial);
95
WITH_JOB_LOCK_GUARD() {
142
if (!n->serial) {
96
g_assert_cmpint(job->job.pause_count, ==, 0);
143
error_setg(errp, "serial property not set");
97
g_assert_false(job->job.paused);
144
return;
98
- g_assert_true(tjob->running);
145
diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
99
+ g_assert_true(qatomic_read(&tjob->running));
146
index XXXXXXX..XXXXXXX 100644
100
g_assert_true(job->job.busy); /* We're in qemu_co_sleep_ns() */
147
--- a/hw/block/virtio-blk.c
148
+++ b/hw/block/virtio-blk.c
149
@@ -XXX,XX +XXX,XX @@ static void virtio_blk_device_realize(DeviceState *dev, Error **errp)
150
return;
151
}
101
}
152
102
153
+ blkconf_serial(&conf->conf, &conf->serial);
103
@@ -XXX,XX +XXX,XX @@ static void test_blockjob_common_drain_node(enum drain_type drain_type,
154
if (!blkconf_apply_backend_options(&conf->conf,
104
*
155
blk_is_read_only(conf->conf.blk), true,
105
* paused is reset in the I/O thread, wait for it
156
errp)) {
106
*/
157
diff --git a/hw/ide/qdev.c b/hw/ide/qdev.c
107
- while (job->job.paused) {
158
index XXXXXXX..XXXXXXX 100644
108
+ while (job_is_paused(&job->job)) {
159
--- a/hw/ide/qdev.c
109
aio_poll(qemu_get_aio_context(), false);
160
+++ b/hw/ide/qdev.c
110
}
161
@@ -XXX,XX +XXX,XX @@ static void ide_dev_initfn(IDEDevice *dev, IDEDriveKind kind, Error **errp)
162
return;
163
}
111
}
164
112
@@ -XXX,XX +XXX,XX @@ static void test_blockjob_common_drain_node(enum drain_type drain_type,
165
+ blkconf_serial(&dev->conf, &dev->serial);
113
*
166
if (kind != IDE_CD) {
114
* paused is reset in the I/O thread, wait for it
167
if (!blkconf_geometry(&dev->conf, &dev->chs_trans, 65535, 16, 255,
115
*/
168
errp)) {
116
- while (job->job.paused) {
169
diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c
117
+ while (job_is_paused(&job->job)) {
170
index XXXXXXX..XXXXXXX 100644
118
aio_poll(qemu_get_aio_context(), false);
171
--- a/hw/scsi/scsi-disk.c
119
}
172
+++ b/hw/scsi/scsi-disk.c
173
@@ -XXX,XX +XXX,XX @@ static void scsi_realize(SCSIDevice *dev, Error **errp)
174
return;
175
}
120
}
176
121
@@ -XXX,XX +XXX,XX @@ static void test_set_aio_context(void)
177
+ blkconf_serial(&s->qdev.conf, &s->serial);
122
178
blkconf_blocksizes(&s->qdev.conf);
123
typedef struct TestDropBackingBlockJob {
179
124
BlockJob common;
180
if (s->qdev.conf.logical_block_size >
125
- bool should_complete;
181
diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c
126
bool *did_complete;
182
index XXXXXXX..XXXXXXX 100644
127
BlockDriverState *detach_also;
183
--- a/hw/usb/dev-storage.c
128
BlockDriverState *bs;
184
+++ b/hw/usb/dev-storage.c
129
+
185
@@ -XXX,XX +XXX,XX @@ static void usb_msd_storage_realize(USBDevice *dev, Error **errp)
130
+ /* Accessed with atomics */
186
return;
131
+ bool should_complete;
132
} TestDropBackingBlockJob;
133
134
static int coroutine_fn test_drop_backing_job_run(Job *job, Error **errp)
135
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn test_drop_backing_job_run(Job *job, Error **errp)
136
TestDropBackingBlockJob *s =
137
container_of(job, TestDropBackingBlockJob, common.job);
138
139
- while (!s->should_complete) {
140
+ while (!qatomic_read(&s->should_complete)) {
141
job_sleep_ns(job, 0);
187
}
142
}
188
143
189
+ blkconf_serial(&s->conf, &dev->serial);
144
@@ -XXX,XX +XXX,XX @@ static void test_blockjob_commit_by_drained_end(void)
190
blkconf_blocksizes(&s->conf);
145
191
if (!blkconf_apply_backend_options(&s->conf, blk_is_read_only(blk), true,
146
job_start(&job->common.job);
192
errp)) {
147
193
diff --git a/tests/ahci-test.c b/tests/ahci-test.c
148
- job->should_complete = true;
194
index XXXXXXX..XXXXXXX 100644
149
+ qatomic_set(&job->should_complete, true);
195
--- a/tests/ahci-test.c
150
bdrv_drained_begin(bs_child);
196
+++ b/tests/ahci-test.c
151
g_assert(!job_has_completed);
197
@@ -XXX,XX +XXX,XX @@ static AHCIQState *ahci_boot(const char *cli, ...)
152
bdrv_drained_end(bs_child);
198
s = ahci_vboot(cli, ap);
153
@@ -XXX,XX +XXX,XX @@ static void test_blockjob_commit_by_drained_end(void)
199
va_end(ap);
154
200
} else {
155
typedef struct TestSimpleBlockJob {
201
- cli = "-drive if=none,id=drive0,file=%s,cache=writeback,format=%s"
156
BlockJob common;
202
+ cli = "-drive if=none,id=drive0,file=%s,cache=writeback,serial=%s"
157
- bool should_complete;
203
+ ",format=%s"
158
bool *did_complete;
204
" -M q35 "
159
+
205
"-device ide-hd,drive=drive0 "
160
+ /* Accessed with atomics */
206
- "-global ide-hd.serial=%s "
161
+ bool should_complete;
207
"-global ide-hd.ver=%s";
162
} TestSimpleBlockJob;
208
- s = ahci_boot(cli, tmp_path, imgfmt, "testdisk", "version");
163
209
+ s = ahci_boot(cli, tmp_path, "testdisk", imgfmt, "version");
164
static int coroutine_fn test_simple_job_run(Job *job, Error **errp)
165
{
166
TestSimpleBlockJob *s = container_of(job, TestSimpleBlockJob, common.job);
167
168
- while (!s->should_complete) {
169
+ while (!qatomic_read(&s->should_complete)) {
170
job_sleep_ns(job, 0);
210
}
171
}
211
172
212
return s;
173
@@ -XXX,XX +XXX,XX @@ static void test_drop_intermediate_poll(void)
213
diff --git a/tests/ide-test.c b/tests/ide-test.c
174
job->did_complete = &job_has_completed;
214
index XXXXXXX..XXXXXXX 100644
175
215
--- a/tests/ide-test.c
176
job_start(&job->common.job);
216
+++ b/tests/ide-test.c
177
- job->should_complete = true;
217
@@ -XXX,XX +XXX,XX @@ static void test_bmdma_no_busmaster(void)
178
+ qatomic_set(&job->should_complete, true);
218
static void test_bmdma_setup(void)
179
219
{
180
g_assert(!job_has_completed);
220
ide_test_start(
181
ret = bdrv_drop_intermediate(chain[1], chain[0], NULL, false);
221
- "-drive file=%s,if=ide,cache=writeback,format=raw "
222
- "-global ide-hd.serial=%s -global ide-hd.ver=%s",
223
+ "-drive file=%s,if=ide,serial=%s,cache=writeback,format=raw "
224
+ "-global ide-hd.ver=%s",
225
tmp_path, "testdisk", "version");
226
qtest_irq_intercept_in(global_qtest, "ioapic");
227
}
228
@@ -XXX,XX +XXX,XX @@ static void test_identify(void)
229
int ret;
230
231
ide_test_start(
232
- "-drive file=%s,if=ide,cache=writeback,format=raw "
233
- "-global ide-hd.serial=%s -global ide-hd.ver=%s",
234
+ "-drive file=%s,if=ide,serial=%s,cache=writeback,format=raw "
235
+ "-global ide-hd.ver=%s",
236
tmp_path, "testdisk", "version");
237
238
dev = get_pci_device(&bmdma_bar, &ide_bar);
239
diff --git a/qemu-doc.texi b/qemu-doc.texi
240
index XXXXXXX..XXXXXXX 100644
241
--- a/qemu-doc.texi
242
+++ b/qemu-doc.texi
243
@@ -XXX,XX +XXX,XX @@ with ``-device ...,netdev=x''), or ``-nic user,smb=/some/dir''
244
(for embedded NICs). The new syntax allows different settings to be
245
provided per NIC.
246
247
+@subsection -drive serial=... (since 2.10.0)
248
+
249
+The drive serial argument is replaced by the the serial argument
250
+that can be specified with the ``-device'' parameter.
251
+
252
@subsection -usbdevice (since 2.10.0)
253
254
The ``-usbdevice DEV'' argument is now a synonym for setting
255
diff --git a/qemu-options.hx b/qemu-options.hx
256
index XXXXXXX..XXXXXXX 100644
257
--- a/qemu-options.hx
258
+++ b/qemu-options.hx
259
@@ -XXX,XX +XXX,XX @@ ETEXI
260
DEF("drive", HAS_ARG, QEMU_OPTION_drive,
261
"-drive [file=file][,if=type][,bus=n][,unit=m][,media=d][,index=i]\n"
262
" [,cache=writethrough|writeback|none|directsync|unsafe][,format=f]\n"
263
- " [,snapshot=on|off][,rerror=ignore|stop|report]\n"
264
+ " [,snapshot=on|off][,serial=s][,rerror=ignore|stop|report]\n"
265
" [,werror=ignore|stop|report|enospc][,id=name][,aio=threads|native]\n"
266
" [,readonly=on|off][,copy-on-read=on|off]\n"
267
" [,discard=ignore|unmap][,detect-zeroes=on|off|unmap]\n"
268
@@ -XXX,XX +XXX,XX @@ The default mode is @option{cache=writeback}.
269
Specify which disk @var{format} will be used rather than detecting
270
the format. Can be used to specify format=raw to avoid interpreting
271
an untrusted format header.
272
+@item serial=@var{serial}
273
+This option specifies the serial number to assign to the device. This
274
+parameter is deprecated, use the corresponding parameter of @code{-device}
275
+instead.
276
@item werror=@var{action},rerror=@var{action}
277
Specify which @var{action} to take on write and read errors. Valid actions are:
278
"ignore" (ignore the error and try to continue), "stop" (pause QEMU),
279
--
182
--
280
2.13.6
183
2.49.0
281
282
diff view generated by jsdifflib
Deleted patch
1
From: Cornelia Huck <cohuck@redhat.com>
2
1
3
This reverts commit eae3bd1eb7c6b105d30ec06008b3bc3dfc5f45bb.
4
5
Reverted to avoid conflicts for geometry options revert.
6
7
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
10
include/sysemu/blockdev.h | 1 +
11
blockdev.c | 17 ++++++++++++++++-
12
device-hotplug.c | 4 ++++
13
qemu-doc.texi | 5 +++++
14
qemu-options.hx | 5 ++++-
15
5 files changed, 30 insertions(+), 2 deletions(-)
16
17
diff --git a/include/sysemu/blockdev.h b/include/sysemu/blockdev.h
18
index XXXXXXX..XXXXXXX 100644
19
--- a/include/sysemu/blockdev.h
20
+++ b/include/sysemu/blockdev.h
21
@@ -XXX,XX +XXX,XX @@ typedef enum {
22
} BlockInterfaceType;
23
24
struct DriveInfo {
25
+ const char *devaddr;
26
BlockInterfaceType type;
27
int bus;
28
int unit;
29
diff --git a/blockdev.c b/blockdev.c
30
index XXXXXXX..XXXXXXX 100644
31
--- a/blockdev.c
32
+++ b/blockdev.c
33
@@ -XXX,XX +XXX,XX @@ QemuOptsList qemu_legacy_drive_opts = {
34
.type = QEMU_OPT_STRING,
35
.help = "interface (ide, scsi, sd, mtd, floppy, pflash, virtio)",
36
},{
37
+ .name = "addr",
38
+ .type = QEMU_OPT_STRING,
39
+ .help = "pci address (virtio only)",
40
+ },{
41
.name = "serial",
42
.type = QEMU_OPT_STRING,
43
.help = "disk serial number",
44
@@ -XXX,XX +XXX,XX @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type)
45
DriveMediaType media = MEDIA_DISK;
46
BlockInterfaceType type;
47
int max_devs, bus_id, unit_id, index;
48
+ const char *devaddr;
49
const char *werror, *rerror;
50
bool read_only = false;
51
bool copy_on_read;
52
@@ -XXX,XX +XXX,XX @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type)
53
Error *local_err = NULL;
54
int i;
55
const char *deprecated[] = {
56
- "serial"
57
+ "serial", "addr"
58
};
59
60
/* Change legacy command line options into QMP ones */
61
@@ -XXX,XX +XXX,XX @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type)
62
}
63
64
/* Add virtio block device */
65
+ devaddr = qemu_opt_get(legacy_opts, "addr");
66
+ if (devaddr && type != IF_VIRTIO) {
67
+ error_report("addr is not supported by this bus type");
68
+ goto fail;
69
+ }
70
+
71
if (type == IF_VIRTIO) {
72
QemuOpts *devopts;
73
devopts = qemu_opts_create(qemu_find_opts("device"), NULL, 0,
74
@@ -XXX,XX +XXX,XX @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type)
75
}
76
qemu_opt_set(devopts, "drive", qdict_get_str(bs_opts, "id"),
77
&error_abort);
78
+ if (devaddr) {
79
+ qemu_opt_set(devopts, "addr", devaddr, &error_abort);
80
+ }
81
}
82
83
filename = qemu_opt_get(legacy_opts, "file");
84
@@ -XXX,XX +XXX,XX @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type)
85
dinfo->type = type;
86
dinfo->bus = bus_id;
87
dinfo->unit = unit_id;
88
+ dinfo->devaddr = devaddr;
89
dinfo->serial = g_strdup(serial);
90
91
blk_set_legacy_dinfo(blk, dinfo);
92
diff --git a/device-hotplug.c b/device-hotplug.c
93
index XXXXXXX..XXXXXXX 100644
94
--- a/device-hotplug.c
95
+++ b/device-hotplug.c
96
@@ -XXX,XX +XXX,XX @@ void hmp_drive_add(Monitor *mon, const QDict *qdict)
97
if (!dinfo) {
98
goto err;
99
}
100
+ if (dinfo->devaddr) {
101
+ monitor_printf(mon, "Parameter addr not supported\n");
102
+ goto err;
103
+ }
104
105
switch (dinfo->type) {
106
case IF_NONE:
107
diff --git a/qemu-doc.texi b/qemu-doc.texi
108
index XXXXXXX..XXXXXXX 100644
109
--- a/qemu-doc.texi
110
+++ b/qemu-doc.texi
111
@@ -XXX,XX +XXX,XX @@ provided per NIC.
112
The drive serial argument is replaced by the the serial argument
113
that can be specified with the ``-device'' parameter.
114
115
+@subsection -drive addr=... (since 2.10.0)
116
+
117
+The drive addr argument is replaced by the the addr argument
118
+that can be specified with the ``-device'' parameter.
119
+
120
@subsection -usbdevice (since 2.10.0)
121
122
The ``-usbdevice DEV'' argument is now a synonym for setting
123
diff --git a/qemu-options.hx b/qemu-options.hx
124
index XXXXXXX..XXXXXXX 100644
125
--- a/qemu-options.hx
126
+++ b/qemu-options.hx
127
@@ -XXX,XX +XXX,XX @@ ETEXI
128
DEF("drive", HAS_ARG, QEMU_OPTION_drive,
129
"-drive [file=file][,if=type][,bus=n][,unit=m][,media=d][,index=i]\n"
130
" [,cache=writethrough|writeback|none|directsync|unsafe][,format=f]\n"
131
- " [,snapshot=on|off][,serial=s][,rerror=ignore|stop|report]\n"
132
+ " [,snapshot=on|off][,serial=s][,addr=A][,rerror=ignore|stop|report]\n"
133
" [,werror=ignore|stop|report|enospc][,id=name][,aio=threads|native]\n"
134
" [,readonly=on|off][,copy-on-read=on|off]\n"
135
" [,discard=ignore|unmap][,detect-zeroes=on|off|unmap]\n"
136
@@ -XXX,XX +XXX,XX @@ an untrusted format header.
137
This option specifies the serial number to assign to the device. This
138
parameter is deprecated, use the corresponding parameter of @code{-device}
139
instead.
140
+@item addr=@var{addr}
141
+Specify the controller's PCI address (if=virtio only). This parameter is
142
+deprecated, use the corresponding parameter of @code{-device} instead.
143
@item werror=@var{action},rerror=@var{action}
144
Specify which @var{action} to take on write and read errors. Valid actions are:
145
"ignore" (ignore the error and try to continue), "stop" (pause QEMU),
146
--
147
2.13.6
148
149
diff view generated by jsdifflib
Deleted patch
1
From: Cornelia Huck <cohuck@redhat.com>
2
1
3
This reverts commit a7aff6dd10b16b67e8b142d0c94c5d92c3fe88f6.
4
5
Hold off removing this for one more QEMU release (current libvirt
6
release still uses it.)
7
8
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
11
include/sysemu/blockdev.h | 1 +
12
blockdev.c | 75 ++++++++++++++++++++++++++++++++++++++++++++++-
13
hw/block/block.c | 14 +++++++++
14
tests/hd-geo-test.c | 37 ++++++++++++++++++-----
15
hmp-commands.hx | 1 +
16
qemu-doc.texi | 5 ++++
17
qemu-options.hx | 7 ++++-
18
7 files changed, 131 insertions(+), 9 deletions(-)
19
20
diff --git a/include/sysemu/blockdev.h b/include/sysemu/blockdev.h
21
index XXXXXXX..XXXXXXX 100644
22
--- a/include/sysemu/blockdev.h
23
+++ b/include/sysemu/blockdev.h
24
@@ -XXX,XX +XXX,XX @@ struct DriveInfo {
25
int auto_del; /* see blockdev_mark_auto_del() */
26
bool is_default; /* Added by default_drive() ? */
27
int media_cd;
28
+ int cyls, heads, secs, trans;
29
QemuOpts *opts;
30
char *serial;
31
QTAILQ_ENTRY(DriveInfo) next;
32
diff --git a/blockdev.c b/blockdev.c
33
index XXXXXXX..XXXXXXX 100644
34
--- a/blockdev.c
35
+++ b/blockdev.c
36
@@ -XXX,XX +XXX,XX @@ QemuOptsList qemu_legacy_drive_opts = {
37
.type = QEMU_OPT_STRING,
38
.help = "interface (ide, scsi, sd, mtd, floppy, pflash, virtio)",
39
},{
40
+ .name = "cyls",
41
+ .type = QEMU_OPT_NUMBER,
42
+ .help = "number of cylinders (ide disk geometry)",
43
+ },{
44
+ .name = "heads",
45
+ .type = QEMU_OPT_NUMBER,
46
+ .help = "number of heads (ide disk geometry)",
47
+ },{
48
+ .name = "secs",
49
+ .type = QEMU_OPT_NUMBER,
50
+ .help = "number of sectors (ide disk geometry)",
51
+ },{
52
+ .name = "trans",
53
+ .type = QEMU_OPT_STRING,
54
+ .help = "chs translation (auto, lba, none)",
55
+ },{
56
.name = "addr",
57
.type = QEMU_OPT_STRING,
58
.help = "pci address (virtio only)",
59
@@ -XXX,XX +XXX,XX @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type)
60
QemuOpts *legacy_opts;
61
DriveMediaType media = MEDIA_DISK;
62
BlockInterfaceType type;
63
+ int cyls, heads, secs, translation;
64
int max_devs, bus_id, unit_id, index;
65
const char *devaddr;
66
const char *werror, *rerror;
67
@@ -XXX,XX +XXX,XX @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type)
68
Error *local_err = NULL;
69
int i;
70
const char *deprecated[] = {
71
- "serial", "addr"
72
+ "serial", "trans", "secs", "heads", "cyls", "addr"
73
};
74
75
/* Change legacy command line options into QMP ones */
76
@@ -XXX,XX +XXX,XX @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type)
77
type = block_default_type;
78
}
79
80
+ /* Geometry */
81
+ cyls = qemu_opt_get_number(legacy_opts, "cyls", 0);
82
+ heads = qemu_opt_get_number(legacy_opts, "heads", 0);
83
+ secs = qemu_opt_get_number(legacy_opts, "secs", 0);
84
+
85
+ if (cyls || heads || secs) {
86
+ if (cyls < 1) {
87
+ error_report("invalid physical cyls number");
88
+ goto fail;
89
+ }
90
+ if (heads < 1) {
91
+ error_report("invalid physical heads number");
92
+ goto fail;
93
+ }
94
+ if (secs < 1) {
95
+ error_report("invalid physical secs number");
96
+ goto fail;
97
+ }
98
+ }
99
+
100
+ translation = BIOS_ATA_TRANSLATION_AUTO;
101
+ value = qemu_opt_get(legacy_opts, "trans");
102
+ if (value != NULL) {
103
+ if (!cyls) {
104
+ error_report("'%s' trans must be used with cyls, heads and secs",
105
+ value);
106
+ goto fail;
107
+ }
108
+ if (!strcmp(value, "none")) {
109
+ translation = BIOS_ATA_TRANSLATION_NONE;
110
+ } else if (!strcmp(value, "lba")) {
111
+ translation = BIOS_ATA_TRANSLATION_LBA;
112
+ } else if (!strcmp(value, "large")) {
113
+ translation = BIOS_ATA_TRANSLATION_LARGE;
114
+ } else if (!strcmp(value, "rechs")) {
115
+ translation = BIOS_ATA_TRANSLATION_RECHS;
116
+ } else if (!strcmp(value, "auto")) {
117
+ translation = BIOS_ATA_TRANSLATION_AUTO;
118
+ } else {
119
+ error_report("'%s' invalid translation type", value);
120
+ goto fail;
121
+ }
122
+ }
123
+
124
+ if (media == MEDIA_CDROM) {
125
+ if (cyls || secs || heads) {
126
+ error_report("CHS can't be set with media=cdrom");
127
+ goto fail;
128
+ }
129
+ }
130
+
131
/* Device address specified by bus/unit or index.
132
* If none was specified, try to find the first free one. */
133
bus_id = qemu_opt_get_number(legacy_opts, "bus", 0);
134
@@ -XXX,XX +XXX,XX @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type)
135
dinfo = g_malloc0(sizeof(*dinfo));
136
dinfo->opts = all_opts;
137
138
+ dinfo->cyls = cyls;
139
+ dinfo->heads = heads;
140
+ dinfo->secs = secs;
141
+ dinfo->trans = translation;
142
+
143
dinfo->type = type;
144
dinfo->bus = bus_id;
145
dinfo->unit = unit_id;
146
diff --git a/hw/block/block.c b/hw/block/block.c
147
index XXXXXXX..XXXXXXX 100644
148
--- a/hw/block/block.c
149
+++ b/hw/block/block.c
150
@@ -XXX,XX +XXX,XX @@ bool blkconf_geometry(BlockConf *conf, int *ptrans,
151
unsigned cyls_max, unsigned heads_max, unsigned secs_max,
152
Error **errp)
153
{
154
+ DriveInfo *dinfo;
155
+
156
+ if (!conf->cyls && !conf->heads && !conf->secs) {
157
+ /* try to fall back to value set with legacy -drive cyls=... */
158
+ dinfo = blk_legacy_dinfo(conf->blk);
159
+ if (dinfo) {
160
+ conf->cyls = dinfo->cyls;
161
+ conf->heads = dinfo->heads;
162
+ conf->secs = dinfo->secs;
163
+ if (ptrans) {
164
+ *ptrans = dinfo->trans;
165
+ }
166
+ }
167
+ }
168
if (!conf->cyls && !conf->heads && !conf->secs) {
169
hd_geometry_guess(conf->blk,
170
&conf->cyls, &conf->heads, &conf->secs,
171
diff --git a/tests/hd-geo-test.c b/tests/hd-geo-test.c
172
index XXXXXXX..XXXXXXX 100644
173
--- a/tests/hd-geo-test.c
174
+++ b/tests/hd-geo-test.c
175
@@ -XXX,XX +XXX,XX @@ static void setup_mbr(int img_idx, MBRcontents mbr)
176
177
static int setup_ide(int argc, char *argv[], int argv_sz,
178
int ide_idx, const char *dev, int img_idx,
179
- MBRcontents mbr)
180
+ MBRcontents mbr, const char *opts)
181
{
182
char *s1, *s2, *s3;
183
184
@@ -XXX,XX +XXX,XX @@ static int setup_ide(int argc, char *argv[], int argv_sz,
185
s3 = g_strdup(",media=cdrom");
186
}
187
argc = append_arg(argc, argv, argv_sz,
188
- g_strdup_printf("%s%s%s", s1, s2, s3));
189
+ g_strdup_printf("%s%s%s%s", s1, s2, s3, opts));
190
g_free(s1);
191
g_free(s2);
192
g_free(s3);
193
@@ -XXX,XX +XXX,XX @@ static void test_ide_mbr(bool use_device, MBRcontents mbr)
194
for (i = 0; i < backend_last; i++) {
195
cur_ide[i] = &hd_chst[i][mbr];
196
dev = use_device ? (is_hd(cur_ide[i]) ? "ide-hd" : "ide-cd") : NULL;
197
- argc = setup_ide(argc, argv, ARGV_SIZE, i, dev, i, mbr);
198
+ argc = setup_ide(argc, argv, ARGV_SIZE, i, dev, i, mbr, "");
199
}
200
args = g_strjoinv(" ", argv);
201
qtest_start(args);
202
@@ -XXX,XX +XXX,XX @@ static void test_ide_drive_user(const char *dev, bool trans)
203
const CHST expected_chst = { secs / (4 * 32) , 4, 32, trans };
204
205
argc = setup_common(argv, ARGV_SIZE);
206
- opts = g_strdup_printf("%s,%scyls=%d,heads=%d,secs=%d",
207
- dev, trans ? "bios-chs-trans=lba," : "",
208
+ opts = g_strdup_printf("%s,%s%scyls=%d,heads=%d,secs=%d",
209
+ dev ?: "",
210
+ trans && dev ? "bios-chs-" : "",
211
+ trans ? "trans=lba," : "",
212
expected_chst.cyls, expected_chst.heads,
213
expected_chst.secs);
214
cur_ide[0] = &expected_chst;
215
- argc = setup_ide(argc, argv, ARGV_SIZE, 0, opts, backend_small, mbr_chs);
216
+ argc = setup_ide(argc, argv, ARGV_SIZE,
217
+ 0, dev ? opts : NULL, backend_small, mbr_chs,
218
+ dev ? "" : opts);
219
g_free(opts);
220
args = g_strjoinv(" ", argv);
221
qtest_start(args);
222
@@ -XXX,XX +XXX,XX @@ static void test_ide_drive_user(const char *dev, bool trans)
223
}
224
225
/*
226
+ * Test case: IDE device (if=ide) with explicit CHS
227
+ */
228
+static void test_ide_drive_user_chs(void)
229
+{
230
+ test_ide_drive_user(NULL, false);
231
+}
232
+
233
+/*
234
+ * Test case: IDE device (if=ide) with explicit CHS and translation
235
+ */
236
+static void test_ide_drive_user_chst(void)
237
+{
238
+ test_ide_drive_user(NULL, true);
239
+}
240
+
241
+/*
242
* Test case: IDE device (if=none) with explicit CHS
243
*/
244
static void test_ide_device_user_chs(void)
245
@@ -XXX,XX +XXX,XX @@ static void test_ide_drive_cd_0(void)
246
for (i = 0; i <= backend_empty; i++) {
247
ide_idx = backend_empty - i;
248
cur_ide[ide_idx] = &hd_chst[i][mbr_blank];
249
- argc = setup_ide(argc, argv, ARGV_SIZE, ide_idx, NULL, i, mbr_blank);
250
+ argc = setup_ide(argc, argv, ARGV_SIZE,
251
+ ide_idx, NULL, i, mbr_blank, "");
252
}
253
args = g_strjoinv(" ", argv);
254
qtest_start(args);
255
@@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv)
256
qtest_add_func("hd-geo/ide/drive/mbr/blank", test_ide_drive_mbr_blank);
257
qtest_add_func("hd-geo/ide/drive/mbr/lba", test_ide_drive_mbr_lba);
258
qtest_add_func("hd-geo/ide/drive/mbr/chs", test_ide_drive_mbr_chs);
259
+ qtest_add_func("hd-geo/ide/drive/user/chs", test_ide_drive_user_chs);
260
+ qtest_add_func("hd-geo/ide/drive/user/chst", test_ide_drive_user_chst);
261
qtest_add_func("hd-geo/ide/drive/cd_0", test_ide_drive_cd_0);
262
qtest_add_func("hd-geo/ide/device/mbr/blank", test_ide_device_mbr_blank);
263
qtest_add_func("hd-geo/ide/device/mbr/lba", test_ide_device_mbr_lba);
264
diff --git a/hmp-commands.hx b/hmp-commands.hx
265
index XXXXXXX..XXXXXXX 100644
266
--- a/hmp-commands.hx
267
+++ b/hmp-commands.hx
268
@@ -XXX,XX +XXX,XX @@ ETEXI
269
.params = "[-n] [[<domain>:]<bus>:]<slot>\n"
270
"[file=file][,if=type][,bus=n]\n"
271
"[,unit=m][,media=d][,index=i]\n"
272
+ "[,cyls=c,heads=h,secs=s[,trans=t]]\n"
273
"[,snapshot=on|off][,cache=on|off]\n"
274
"[,readonly=on|off][,copy-on-read=on|off]",
275
.help = "add drive to PCI storage controller",
276
diff --git a/qemu-doc.texi b/qemu-doc.texi
277
index XXXXXXX..XXXXXXX 100644
278
--- a/qemu-doc.texi
279
+++ b/qemu-doc.texi
280
@@ -XXX,XX +XXX,XX @@ with ``-device ...,netdev=x''), or ``-nic user,smb=/some/dir''
281
(for embedded NICs). The new syntax allows different settings to be
282
provided per NIC.
283
284
+@subsection -drive cyls=...,heads=...,secs=...,trans=... (since 2.10.0)
285
+
286
+The drive geometry arguments are replaced by the the geometry arguments
287
+that can be specified with the ``-device'' parameter.
288
+
289
@subsection -drive serial=... (since 2.10.0)
290
291
The drive serial argument is replaced by the the serial argument
292
diff --git a/qemu-options.hx b/qemu-options.hx
293
index XXXXXXX..XXXXXXX 100644
294
--- a/qemu-options.hx
295
+++ b/qemu-options.hx
296
@@ -XXX,XX +XXX,XX @@ ETEXI
297
298
DEF("drive", HAS_ARG, QEMU_OPTION_drive,
299
"-drive [file=file][,if=type][,bus=n][,unit=m][,media=d][,index=i]\n"
300
+ " [,cyls=c,heads=h,secs=s[,trans=t]][,snapshot=on|off]\n"
301
" [,cache=writethrough|writeback|none|directsync|unsafe][,format=f]\n"
302
- " [,snapshot=on|off][,serial=s][,addr=A][,rerror=ignore|stop|report]\n"
303
+ " [,serial=s][,addr=A][,rerror=ignore|stop|report]\n"
304
" [,werror=ignore|stop|report|enospc][,id=name][,aio=threads|native]\n"
305
" [,readonly=on|off][,copy-on-read=on|off]\n"
306
" [,discard=ignore|unmap][,detect-zeroes=on|off|unmap]\n"
307
@@ -XXX,XX +XXX,XX @@ This option defines where is connected the drive by using an index in the list
308
of available connectors of a given interface type.
309
@item media=@var{media}
310
This option defines the type of the media: disk or cdrom.
311
+@item cyls=@var{c},heads=@var{h},secs=@var{s}[,trans=@var{t}]
312
+Force disk physical geometry and the optional BIOS translation (trans=none or
313
+lba). These parameters are deprecated, use the corresponding parameters
314
+of @code{-device} instead.
315
@item snapshot=@var{snapshot}
316
@var{snapshot} is "on" or "off" and controls snapshot mode for the given drive
317
(see @option{-snapshot}).
318
--
319
2.13.6
320
321
diff view generated by jsdifflib
Deleted patch
1
From: Fam Zheng <famz@redhat.com>
2
1
3
With in one module, trace points usually have a common prefix named
4
after the module name. paio_submit and paio_submit_co are the only two
5
trace points so far in the two file protocol drivers. As we are adding
6
more, having a common prefix here is better so that trace points can be
7
enabled with a glob. Rename them.
8
9
Suggested-by: Kevin Wolf <kwolf@redhat.com>
10
Signed-off-by: Fam Zheng <famz@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
---
13
block/file-posix.c | 2 +-
14
block/file-win32.c | 2 +-
15
block/trace-events | 4 ++--
16
3 files changed, 4 insertions(+), 4 deletions(-)
17
18
diff --git a/block/file-posix.c b/block/file-posix.c
19
index XXXXXXX..XXXXXXX 100644
20
--- a/block/file-posix.c
21
+++ b/block/file-posix.c
22
@@ -XXX,XX +XXX,XX @@ static int paio_submit_co_full(BlockDriverState *bs, int fd,
23
assert(qiov->size == bytes);
24
}
25
26
- trace_paio_submit_co(offset, bytes, type);
27
+ trace_file_paio_submit_co(offset, bytes, type);
28
pool = aio_get_thread_pool(bdrv_get_aio_context(bs));
29
return thread_pool_submit_co(pool, aio_worker, acb);
30
}
31
diff --git a/block/file-win32.c b/block/file-win32.c
32
index XXXXXXX..XXXXXXX 100644
33
--- a/block/file-win32.c
34
+++ b/block/file-win32.c
35
@@ -XXX,XX +XXX,XX @@ static BlockAIOCB *paio_submit(BlockDriverState *bs, HANDLE hfile,
36
acb->aio_nbytes = count;
37
acb->aio_offset = offset;
38
39
- trace_paio_submit(acb, opaque, offset, count, type);
40
+ trace_file_paio_submit(acb, opaque, offset, count, type);
41
pool = aio_get_thread_pool(bdrv_get_aio_context(bs));
42
return thread_pool_submit_aio(pool, aio_worker, acb, cb, opaque);
43
}
44
diff --git a/block/trace-events b/block/trace-events
45
index XXXXXXX..XXXXXXX 100644
46
--- a/block/trace-events
47
+++ b/block/trace-events
48
@@ -XXX,XX +XXX,XX @@ qmp_block_stream(void *bs, void *job) "bs %p job %p"
49
50
# block/file-win32.c
51
# block/file-posix.c
52
-paio_submit_co(int64_t offset, int count, int type) "offset %"PRId64" count %d type %d"
53
-paio_submit(void *acb, void *opaque, int64_t offset, int count, int type) "acb %p opaque %p offset %"PRId64" count %d type %d"
54
+file_paio_submit_co(int64_t offset, int count, int type) "offset %"PRId64" count %d type %d"
55
+file_paio_submit(void *acb, void *opaque, int64_t offset, int count, int type) "acb %p opaque %p offset %"PRId64" count %d type %d"
56
57
# block/qcow2.c
58
qcow2_writev_start_req(void *co, int64_t offset, int bytes) "co %p offset 0x%" PRIx64 " bytes %d"
59
--
60
2.13.6
61
62
diff view generated by jsdifflib
Deleted patch
1
From: Fam Zheng <famz@redhat.com>
2
1
3
A few trace points that can help reveal what is happening in a copy
4
offloading I/O path.
5
6
Signed-off-by: Fam Zheng <famz@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
---
9
block/file-posix.c | 2 ++
10
block/io.c | 4 ++++
11
block/iscsi.c | 3 +++
12
block/trace-events | 6 ++++++
13
4 files changed, 15 insertions(+)
14
15
diff --git a/block/file-posix.c b/block/file-posix.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/block/file-posix.c
18
+++ b/block/file-posix.c
19
@@ -XXX,XX +XXX,XX @@ static ssize_t handle_aiocb_copy_range(RawPosixAIOData *aiocb)
20
ssize_t ret = copy_file_range(aiocb->aio_fildes, &in_off,
21
aiocb->aio_fd2, &out_off,
22
bytes, 0);
23
+ trace_file_copy_file_range(aiocb->bs, aiocb->aio_fildes, in_off,
24
+ aiocb->aio_fd2, out_off, bytes, 0, ret);
25
if (ret == 0) {
26
/* No progress (e.g. when beyond EOF), let the caller fall back to
27
* buffer I/O. */
28
diff --git a/block/io.c b/block/io.c
29
index XXXXXXX..XXXXXXX 100644
30
--- a/block/io.c
31
+++ b/block/io.c
32
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_copy_range_from(BdrvChild *src, uint64_t src_offset,
33
BdrvRequestFlags read_flags,
34
BdrvRequestFlags write_flags)
35
{
36
+ trace_bdrv_co_copy_range_from(src, src_offset, dst, dst_offset, bytes,
37
+ read_flags, write_flags);
38
return bdrv_co_copy_range_internal(src, src_offset, dst, dst_offset,
39
bytes, read_flags, write_flags, true);
40
}
41
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_copy_range_to(BdrvChild *src, uint64_t src_offset,
42
BdrvRequestFlags read_flags,
43
BdrvRequestFlags write_flags)
44
{
45
+ trace_bdrv_co_copy_range_to(src, src_offset, dst, dst_offset, bytes,
46
+ read_flags, write_flags);
47
return bdrv_co_copy_range_internal(src, src_offset, dst, dst_offset,
48
bytes, read_flags, write_flags, false);
49
}
50
diff --git a/block/iscsi.c b/block/iscsi.c
51
index XXXXXXX..XXXXXXX 100644
52
--- a/block/iscsi.c
53
+++ b/block/iscsi.c
54
@@ -XXX,XX +XXX,XX @@
55
#include "qapi/qmp/qstring.h"
56
#include "crypto/secret.h"
57
#include "scsi/utils.h"
58
+#include "trace.h"
59
60
/* Conflict between scsi/utils.h and libiscsi! :( */
61
#define SCSI_XFER_NONE ISCSI_XFER_NONE
62
@@ -XXX,XX +XXX,XX @@ retry:
63
}
64
65
out_unlock:
66
+
67
+ trace_iscsi_xcopy(src_lun, src_offset, dst_lun, dst_offset, bytes, r);
68
g_free(iscsi_task.task);
69
qemu_mutex_unlock(&dst_lun->mutex);
70
g_free(iscsi_task.err_str);
71
diff --git a/block/trace-events b/block/trace-events
72
index XXXXXXX..XXXXXXX 100644
73
--- a/block/trace-events
74
+++ b/block/trace-events
75
@@ -XXX,XX +XXX,XX @@ bdrv_co_preadv(void *bs, int64_t offset, int64_t nbytes, unsigned int flags) "bs
76
bdrv_co_pwritev(void *bs, int64_t offset, int64_t nbytes, unsigned int flags) "bs %p offset %"PRId64" nbytes %"PRId64" flags 0x%x"
77
bdrv_co_pwrite_zeroes(void *bs, int64_t offset, int count, int flags) "bs %p offset %"PRId64" count %d flags 0x%x"
78
bdrv_co_do_copy_on_readv(void *bs, int64_t offset, unsigned int bytes, int64_t cluster_offset, int64_t cluster_bytes) "bs %p offset %"PRId64" bytes %u cluster_offset %"PRId64" cluster_bytes %"PRId64
79
+bdrv_co_copy_range_from(void *src, uint64_t src_offset, void *dst, uint64_t dst_offset, uint64_t bytes, int read_flags, int write_flags) "src %p offset %"PRIu64" dst %p offset %"PRIu64" bytes %"PRIu64" rw flags 0x%x 0x%x"
80
+bdrv_co_copy_range_to(void *src, uint64_t src_offset, void *dst, uint64_t dst_offset, uint64_t bytes, int read_flags, int write_flags) "src %p offset %"PRIu64" dst %p offset %"PRIu64" bytes %"PRIu64" rw flags 0x%x 0x%x"
81
82
# block/stream.c
83
stream_one_iteration(void *s, int64_t offset, uint64_t bytes, int is_allocated) "s %p offset %" PRId64 " bytes %" PRIu64 " is_allocated %d"
84
@@ -XXX,XX +XXX,XX @@ qmp_block_stream(void *bs, void *job) "bs %p job %p"
85
# block/file-posix.c
86
file_paio_submit_co(int64_t offset, int count, int type) "offset %"PRId64" count %d type %d"
87
file_paio_submit(void *acb, void *opaque, int64_t offset, int count, int type) "acb %p opaque %p offset %"PRId64" count %d type %d"
88
+file_copy_file_range(void *bs, int src, int64_t src_off, int dst, int64_t dst_off, int64_t bytes, int flags, int64_t ret) "bs %p src_fd %d offset %"PRIu64" dst_fd %d offset %"PRIu64" bytes %"PRIu64" flags %d ret %"PRId64
89
90
# block/qcow2.c
91
qcow2_writev_start_req(void *co, int64_t offset, int bytes) "co %p offset 0x%" PRIx64 " bytes %d"
92
@@ -XXX,XX +XXX,XX @@ nvme_free_req_queue_wait(void *q) "q %p"
93
nvme_cmd_map_qiov(void *s, void *cmd, void *req, void *qiov, int entries) "s %p cmd %p req %p qiov %p entries %d"
94
nvme_cmd_map_qiov_pages(void *s, int i, uint64_t page) "s %p page[%d] 0x%"PRIx64
95
nvme_cmd_map_qiov_iov(void *s, int i, void *page, int pages) "s %p iov[%d] %p pages %d"
96
+
97
+# block/iscsi.c
98
+iscsi_xcopy(void *src_lun, uint64_t src_off, void *dst_lun, uint64_t dst_off, uint64_t bytes, int ret) "src_lun %p offset %"PRIu64" dst_lun %p offset %"PRIu64" bytes %"PRIu64" ret %d"
99
--
100
2.13.6
101
102
diff view generated by jsdifflib
Deleted patch
1
From: Fam Zheng <famz@redhat.com>
2
1
3
This matches the types used for bytes in the rest parts of block layer.
4
In the case of bdrv_co_truncate, new_bytes can be the image size which
5
probably doesn't fit in a 32 bit int.
6
7
Signed-off-by: Fam Zheng <famz@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
10
include/block/block_int.h | 4 ++--
11
block/io.c | 8 +++++---
12
2 files changed, 7 insertions(+), 5 deletions(-)
13
14
diff --git a/include/block/block_int.h b/include/block/block_int.h
15
index XXXXXXX..XXXXXXX 100644
16
--- a/include/block/block_int.h
17
+++ b/include/block/block_int.h
18
@@ -XXX,XX +XXX,XX @@ enum BdrvTrackedRequestType {
19
typedef struct BdrvTrackedRequest {
20
BlockDriverState *bs;
21
int64_t offset;
22
- unsigned int bytes;
23
+ uint64_t bytes;
24
enum BdrvTrackedRequestType type;
25
26
bool serialising;
27
int64_t overlap_offset;
28
- unsigned int overlap_bytes;
29
+ uint64_t overlap_bytes;
30
31
QLIST_ENTRY(BdrvTrackedRequest) list;
32
Coroutine *co; /* owner, used for deadlock detection */
33
diff --git a/block/io.c b/block/io.c
34
index XXXXXXX..XXXXXXX 100644
35
--- a/block/io.c
36
+++ b/block/io.c
37
@@ -XXX,XX +XXX,XX @@ static void tracked_request_end(BdrvTrackedRequest *req)
38
static void tracked_request_begin(BdrvTrackedRequest *req,
39
BlockDriverState *bs,
40
int64_t offset,
41
- unsigned int bytes,
42
+ uint64_t bytes,
43
enum BdrvTrackedRequestType type)
44
{
45
+ assert(bytes <= INT64_MAX && offset <= INT64_MAX - bytes);
46
+
47
*req = (BdrvTrackedRequest){
48
.bs = bs,
49
.offset = offset,
50
@@ -XXX,XX +XXX,XX @@ static void tracked_request_begin(BdrvTrackedRequest *req,
51
static void mark_request_serialising(BdrvTrackedRequest *req, uint64_t align)
52
{
53
int64_t overlap_offset = req->offset & ~(align - 1);
54
- unsigned int overlap_bytes = ROUND_UP(req->offset + req->bytes, align)
55
+ uint64_t overlap_bytes = ROUND_UP(req->offset + req->bytes, align)
56
- overlap_offset;
57
58
if (!req->serialising) {
59
@@ -XXX,XX +XXX,XX @@ static int bdrv_get_cluster_size(BlockDriverState *bs)
60
}
61
62
static bool tracked_request_overlaps(BdrvTrackedRequest *req,
63
- int64_t offset, unsigned int bytes)
64
+ int64_t offset, uint64_t bytes)
65
{
66
/* aaaa bbbb */
67
if (offset >= req->overlap_offset + req->overlap_bytes) {
68
--
69
2.13.6
70
71
diff view generated by jsdifflib
Deleted patch
1
From: Fam Zheng <famz@redhat.com>
2
1
3
As a mechanical refactoring patch, this is the first step towards
4
unified and more correct write code paths. This is helpful because
5
multiple BlockDriverState fields need to be updated after modifying
6
image data, and it's hard to maintain in multiple places such as copy
7
offload, discard and truncate.
8
9
Suggested-by: Kevin Wolf <kwolf@redhat.com>
10
Signed-off-by: Fam Zheng <famz@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
---
13
block/io.c | 91 +++++++++++++++++++++++++++++++++++++++-----------------------
14
1 file changed, 57 insertions(+), 34 deletions(-)
15
16
diff --git a/block/io.c b/block/io.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/block/io.c
19
+++ b/block/io.c
20
@@ -XXX,XX +XXX,XX @@ fail:
21
return ret;
22
}
23
24
+static inline int coroutine_fn
25
+bdrv_co_write_req_prepare(BdrvChild *child, int64_t offset, uint64_t bytes,
26
+ BdrvTrackedRequest *req, int flags)
27
+{
28
+ BlockDriverState *bs = child->bs;
29
+ bool waited;
30
+ int64_t end_sector = DIV_ROUND_UP(offset + bytes, BDRV_SECTOR_SIZE);
31
+
32
+ if (bs->read_only) {
33
+ return -EPERM;
34
+ }
35
+
36
+ /* BDRV_REQ_NO_SERIALISING is only for read operation */
37
+ assert(!(flags & BDRV_REQ_NO_SERIALISING));
38
+ assert(!(bs->open_flags & BDRV_O_INACTIVE));
39
+ assert((bs->open_flags & BDRV_O_NO_IO) == 0);
40
+ assert(!(flags & ~BDRV_REQ_MASK));
41
+
42
+ if (flags & BDRV_REQ_SERIALISING) {
43
+ mark_request_serialising(req, bdrv_get_cluster_size(bs));
44
+ }
45
+
46
+ waited = wait_serialising_requests(req);
47
+
48
+ assert(!waited || !req->serialising ||
49
+ is_request_serialising_and_aligned(req));
50
+ assert(req->overlap_offset <= offset);
51
+ assert(offset + bytes <= req->overlap_offset + req->overlap_bytes);
52
+
53
+ if (flags & BDRV_REQ_WRITE_UNCHANGED) {
54
+ assert(child->perm & (BLK_PERM_WRITE_UNCHANGED | BLK_PERM_WRITE));
55
+ } else {
56
+ assert(child->perm & BLK_PERM_WRITE);
57
+ }
58
+ assert(end_sector <= bs->total_sectors || child->perm & BLK_PERM_RESIZE);
59
+ return notifier_with_return_list_notify(&bs->before_write_notifiers, req);
60
+}
61
+
62
+static inline void coroutine_fn
63
+bdrv_co_write_req_finish(BdrvChild *child, int64_t offset, uint64_t bytes,
64
+ BdrvTrackedRequest *req, int ret)
65
+{
66
+ int64_t end_sector = DIV_ROUND_UP(offset + bytes, BDRV_SECTOR_SIZE);
67
+ BlockDriverState *bs = child->bs;
68
+
69
+ atomic_inc(&bs->write_gen);
70
+ bdrv_set_dirty(bs, offset, bytes);
71
+
72
+ stat64_max(&bs->wr_highest_offset, offset + bytes);
73
+
74
+ if (ret == 0) {
75
+ bs->total_sectors = MAX(bs->total_sectors, end_sector);
76
+ }
77
+}
78
+
79
/*
80
* Forwards an already correctly aligned write request to the BlockDriver,
81
* after possibly fragmenting it.
82
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_aligned_pwritev(BdrvChild *child,
83
{
84
BlockDriverState *bs = child->bs;
85
BlockDriver *drv = bs->drv;
86
- bool waited;
87
int ret;
88
89
- int64_t end_sector = DIV_ROUND_UP(offset + bytes, BDRV_SECTOR_SIZE);
90
uint64_t bytes_remaining = bytes;
91
int max_transfer;
92
93
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_aligned_pwritev(BdrvChild *child,
94
assert((offset & (align - 1)) == 0);
95
assert((bytes & (align - 1)) == 0);
96
assert(!qiov || bytes == qiov->size);
97
- assert((bs->open_flags & BDRV_O_NO_IO) == 0);
98
- assert(!(flags & ~BDRV_REQ_MASK));
99
max_transfer = QEMU_ALIGN_DOWN(MIN_NON_ZERO(bs->bl.max_transfer, INT_MAX),
100
align);
101
102
- /* BDRV_REQ_NO_SERIALISING is only for read operation */
103
- assert(!(flags & BDRV_REQ_NO_SERIALISING));
104
-
105
- if (flags & BDRV_REQ_SERIALISING) {
106
- mark_request_serialising(req, bdrv_get_cluster_size(bs));
107
- }
108
-
109
- waited = wait_serialising_requests(req);
110
- assert(!waited || !req->serialising ||
111
- is_request_serialising_and_aligned(req));
112
- assert(req->overlap_offset <= offset);
113
- assert(offset + bytes <= req->overlap_offset + req->overlap_bytes);
114
- if (flags & BDRV_REQ_WRITE_UNCHANGED) {
115
- assert(child->perm & (BLK_PERM_WRITE_UNCHANGED | BLK_PERM_WRITE));
116
- } else {
117
- assert(child->perm & BLK_PERM_WRITE);
118
- }
119
- assert(end_sector <= bs->total_sectors || child->perm & BLK_PERM_RESIZE);
120
-
121
- ret = notifier_with_return_list_notify(&bs->before_write_notifiers, req);
122
+ ret = bdrv_co_write_req_prepare(child, offset, bytes, req, flags);
123
124
if (!ret && bs->detect_zeroes != BLOCKDEV_DETECT_ZEROES_OPTIONS_OFF &&
125
!(flags & BDRV_REQ_ZERO_WRITE) && drv->bdrv_co_pwrite_zeroes &&
126
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_aligned_pwritev(BdrvChild *child,
127
}
128
bdrv_debug_event(bs, BLKDBG_PWRITEV_DONE);
129
130
- atomic_inc(&bs->write_gen);
131
- bdrv_set_dirty(bs, offset, bytes);
132
-
133
- stat64_max(&bs->wr_highest_offset, offset + bytes);
134
-
135
if (ret >= 0) {
136
- bs->total_sectors = MAX(bs->total_sectors, end_sector);
137
ret = 0;
138
}
139
+ bdrv_co_write_req_finish(child, offset, bytes, req, ret);
140
141
return ret;
142
}
143
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_pwritev(BdrvChild *child,
144
if (!bs->drv) {
145
return -ENOMEDIUM;
146
}
147
- if (bs->read_only) {
148
- return -EPERM;
149
- }
150
- assert(!(bs->open_flags & BDRV_O_INACTIVE));
151
152
ret = bdrv_check_byte_request(bs, offset, bytes);
153
if (ret < 0) {
154
--
155
2.13.6
156
157
diff view generated by jsdifflib
Deleted patch
1
From: Fam Zheng <famz@redhat.com>
2
1
3
Two problems exist when a write request that enlarges the image (i.e.
4
write beyond EOF) finishes:
5
6
1) parent is not notified about size change;
7
2) dirty bitmap is not resized although we try to set the dirty bits;
8
9
Fix them just like how bdrv_co_truncate works.
10
11
Reported-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Fam Zheng <famz@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
---
15
block/io.c | 10 +++++++---
16
1 file changed, 7 insertions(+), 3 deletions(-)
17
18
diff --git a/block/io.c b/block/io.c
19
index XXXXXXX..XXXXXXX 100644
20
--- a/block/io.c
21
+++ b/block/io.c
22
@@ -XXX,XX +XXX,XX @@
23
24
static AioWait drain_all_aio_wait;
25
26
+static void bdrv_parent_cb_resize(BlockDriverState *bs);
27
static int coroutine_fn bdrv_co_do_pwrite_zeroes(BlockDriverState *bs,
28
int64_t offset, int bytes, BdrvRequestFlags flags);
29
30
@@ -XXX,XX +XXX,XX @@ bdrv_co_write_req_finish(BdrvChild *child, int64_t offset, uint64_t bytes,
31
BlockDriverState *bs = child->bs;
32
33
atomic_inc(&bs->write_gen);
34
- bdrv_set_dirty(bs, offset, bytes);
35
36
stat64_max(&bs->wr_highest_offset, offset + bytes);
37
38
- if (ret == 0) {
39
- bs->total_sectors = MAX(bs->total_sectors, end_sector);
40
+ if (ret == 0 &&
41
+ end_sector > bs->total_sectors) {
42
+ bs->total_sectors = end_sector;
43
+ bdrv_parent_cb_resize(bs);
44
+ bdrv_dirty_bitmap_truncate(bs, end_sector << BDRV_SECTOR_BITS);
45
}
46
+ bdrv_set_dirty(bs, offset, bytes);
47
}
48
49
/*
50
--
51
2.13.6
52
53
diff view generated by jsdifflib
Deleted patch
1
From: Fam Zheng <famz@redhat.com>
2
1
3
Reuse the new bdrv_co_write_req_prepare/finish helpers. The variation
4
here is that discard requests don't affect bs->wr_highest_offset, and it
5
cannot extend the image.
6
7
Signed-off-by: Fam Zheng <famz@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
10
block/io.c | 33 +++++++++++++++++++++++----------
11
1 file changed, 23 insertions(+), 10 deletions(-)
12
13
diff --git a/block/io.c b/block/io.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/block/io.c
16
+++ b/block/io.c
17
@@ -XXX,XX +XXX,XX @@ bdrv_co_write_req_finish(BdrvChild *child, int64_t offset, uint64_t bytes,
18
19
atomic_inc(&bs->write_gen);
20
21
- stat64_max(&bs->wr_highest_offset, offset + bytes);
22
-
23
+ /*
24
+ * Discard cannot extend the image, but in error handling cases, such as
25
+ * when reverting a qcow2 cluster allocation, the discarded range can pass
26
+ * the end of image file, so we cannot assert about BDRV_TRACKED_DISCARD
27
+ * here. Instead, just skip it, since semantically a discard request
28
+ * beyond EOF cannot expand the image anyway.
29
+ */
30
if (ret == 0 &&
31
- end_sector > bs->total_sectors) {
32
+ end_sector > bs->total_sectors &&
33
+ req->type != BDRV_TRACKED_DISCARD) {
34
bs->total_sectors = end_sector;
35
bdrv_parent_cb_resize(bs);
36
bdrv_dirty_bitmap_truncate(bs, end_sector << BDRV_SECTOR_BITS);
37
}
38
- bdrv_set_dirty(bs, offset, bytes);
39
+ if (req->bytes) {
40
+ switch (req->type) {
41
+ case BDRV_TRACKED_WRITE:
42
+ stat64_max(&bs->wr_highest_offset, offset + bytes);
43
+ /* fall through, to set dirty bits */
44
+ case BDRV_TRACKED_DISCARD:
45
+ bdrv_set_dirty(bs, offset, bytes);
46
+ break;
47
+ default:
48
+ break;
49
+ }
50
+ }
51
}
52
53
/*
54
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_pdiscard(BdrvChild *child, int64_t offset, int bytes)
55
ret = bdrv_check_byte_request(bs, offset, bytes);
56
if (ret < 0) {
57
return ret;
58
- } else if (bs->read_only) {
59
- return -EPERM;
60
}
61
- assert(!(bs->open_flags & BDRV_O_INACTIVE));
62
63
/* Do nothing if disabled. */
64
if (!(bs->open_flags & BDRV_O_UNMAP)) {
65
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_pdiscard(BdrvChild *child, int64_t offset, int bytes)
66
bdrv_inc_in_flight(bs);
67
tracked_request_begin(&req, bs, offset, bytes, BDRV_TRACKED_DISCARD);
68
69
- ret = notifier_with_return_list_notify(&bs->before_write_notifiers, &req);
70
+ ret = bdrv_co_write_req_prepare(child, offset, bytes, &req, 0);
71
if (ret < 0) {
72
goto out;
73
}
74
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_pdiscard(BdrvChild *child, int64_t offset, int bytes)
75
}
76
ret = 0;
77
out:
78
- atomic_inc(&bs->write_gen);
79
- bdrv_set_dirty(bs, req.offset, req.bytes);
80
+ bdrv_co_write_req_finish(child, req.offset, req.bytes, &req, ret);
81
tracked_request_end(&req);
82
bdrv_dec_in_flight(bs);
83
return ret;
84
--
85
2.13.6
86
87
diff view generated by jsdifflib
Deleted patch
1
From: Fam Zheng <famz@redhat.com>
2
1
3
This brings the request handling logic inline with write and discard,
4
fixing write_gen, resize_cb, dirty bitmaps and image size refreshing.
5
The last of these issues broke iotest case 222, which is now fixed.
6
7
Signed-off-by: Fam Zheng <famz@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
10
block/io.c | 24 ++++++++++--------------
11
1 file changed, 10 insertions(+), 14 deletions(-)
12
13
diff --git a/block/io.c b/block/io.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/block/io.c
16
+++ b/block/io.c
17
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_co_copy_range_internal(
18
bdrv_inc_in_flight(dst->bs);
19
tracked_request_begin(&req, dst->bs, dst_offset, bytes,
20
BDRV_TRACKED_WRITE);
21
-
22
- /* BDRV_REQ_NO_SERIALISING is only for read operation */
23
- assert(!(write_flags & BDRV_REQ_NO_SERIALISING));
24
- if (write_flags & BDRV_REQ_SERIALISING) {
25
- mark_request_serialising(&req, bdrv_get_cluster_size(dst->bs));
26
- }
27
- wait_serialising_requests(&req);
28
-
29
- ret = dst->bs->drv->bdrv_co_copy_range_to(dst->bs,
30
- src, src_offset,
31
- dst, dst_offset,
32
- bytes,
33
- read_flags, write_flags);
34
-
35
+ ret = bdrv_co_write_req_prepare(dst, dst_offset, bytes, &req,
36
+ write_flags);
37
+ if (!ret) {
38
+ ret = dst->bs->drv->bdrv_co_copy_range_to(dst->bs,
39
+ src, src_offset,
40
+ dst, dst_offset,
41
+ bytes,
42
+ read_flags, write_flags);
43
+ }
44
+ bdrv_co_write_req_finish(dst, dst_offset, bytes, &req, ret);
45
tracked_request_end(&req);
46
bdrv_dec_in_flight(dst->bs);
47
}
48
--
49
2.13.6
50
51
diff view generated by jsdifflib
Deleted patch
1
From: Fam Zheng <famz@redhat.com>
2
1
3
If we are growing the image and potentially using preallocation for the
4
new area, we need to make sure that no write requests are made to the
5
"preallocated" area which is [@old_size, @offset), not
6
[@offset, offset * 2 - @old_size).
7
8
Signed-off-by: Fam Zheng <famz@redhat.com>
9
Reviewed-by: Eric Blake <eblake@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
---
12
block/io.c | 3 ++-
13
1 file changed, 2 insertions(+), 1 deletion(-)
14
15
diff --git a/block/io.c b/block/io.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/block/io.c
18
+++ b/block/io.c
19
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset,
20
}
21
22
bdrv_inc_in_flight(bs);
23
- tracked_request_begin(&req, bs, offset, new_bytes, BDRV_TRACKED_TRUNCATE);
24
+ tracked_request_begin(&req, bs, offset - new_bytes, new_bytes,
25
+ BDRV_TRACKED_TRUNCATE);
26
27
/* If we are growing the image and potentially using preallocation for the
28
* new area, we need to make sure that no write requests are made to it
29
--
30
2.13.6
31
32
diff view generated by jsdifflib