1
The following changes since commit b34181056c04e05db6c632063012beaee7006a37:
1
The following changes since commit 143c2e0432859826c9e8d5b2baa307355f1a5332:
2
2
3
Merge remote-tracking branch 'remotes/rth/tags/pull-sh4-20180709' into staging (2018-07-09 22:44:22 +0100)
3
Merge remote-tracking branch 'remotes/maxreitz/tags/pull-block-2021-07-19' into staging (2021-07-19 19:06:05 +0100)
4
4
5
are available in the git repository at:
5
are available in the Git repository at:
6
6
7
git://repo.or.cz/qemu/kevin.git tags/for-upstream
7
git://repo.or.cz/qemu/kevin.git tags/for-upstream
8
8
9
for you to fetch changes up to cd47d792d7a27a57f4b621e2ff1ed8f4e83de1e9:
9
for you to fetch changes up to d21471696b07f30cb00453709d055a25c1afde85:
10
10
11
block: Use common write req handling in truncate (2018-07-10 16:46:22 +0200)
11
iotests/307: Test iothread conflict for exports (2021-07-20 16:49:50 +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
- mirror: Fix active mirror deadlock
17
- Temporary revert of the removal of deprecated -drive options
17
- replication: Fix crashes due to operations on wrong BdrvChild
18
- Fix request serialisation in the image fleecing scenario
18
- configure: Add option to use driver whitelist even in tools
19
- Fix copy-on-read crash with unaligned image size
19
- vvfat: Fix crash when opening image read-write
20
- Fix another drain crash
20
- export: Fix crash in error path with fixed-iothread=false
21
21
22
----------------------------------------------------------------
22
----------------------------------------------------------------
23
Ari Sundholm (2):
23
Kevin Wolf (1):
24
qapi/block-core.json: Add missing documentation for blklogwrites log-append option
24
block: Add option to use driver whitelist even in tools
25
block/blklogwrites: Make sure the log sector size is not too small
26
25
27
Cornelia Huck (4):
26
Lukas Straub (4):
28
Revert "block: Remove dead deprecation warning code"
27
replication: Remove s->active_disk
29
Revert "block: Remove deprecated -drive option serial"
28
replication: Reduce usage of s->hidden_disk and s->secondary_disk
30
Revert "block: Remove deprecated -drive option addr"
29
replication: Properly attach children
31
Revert "block: Remove deprecated -drive geometry options"
30
replication: Remove workaround
32
31
33
Fam Zheng (11):
32
Max Reitz (2):
34
iotests: 222: Don't run with luks
33
block/export: Conditionally ignore set-context error
35
block: Prefix file driver trace points with "file_"
34
iotests/307: Test iothread conflict for exports
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
46
Kevin Wolf (3):
47
block: Poll after drain on attaching a node
48
test-bdrv-drain: Test bdrv_append() to drained node
49
block: Fix copy-on-read crash with partial final cluster
50
35
51
Vladimir Sementsov-Ogievskiy (4):
36
Vladimir Sementsov-Ogievskiy (4):
52
block/io: fix copy_range
37
block/mirror: set .co for active-write MirrorOp objects
53
block: split flags in copy_range
38
iotest 151: add test-case that shows active mirror dead-lock
54
block: add BDRV_REQ_SERIALISING flag
39
block/mirror: fix active mirror dead-lock in mirror_wait_on_conflicts
55
block/backup: fix fleecing scheme: use serialized writes
40
block/vvfat: fix: drop backing
56
41
57
qapi/block-core.json | 2 +
42
configure | 14 +++++-
58
include/block/block.h | 41 +++++-
43
block.c | 3 ++
59
include/block/block_int.h | 21 ++-
44
block/export/export.c | 5 +-
60
include/hw/block/block.h | 1 +
45
block/mirror.c | 13 ++++++
61
include/sysemu/block-backend.h | 3 +-
46
block/replication.c | 111 +++++++++++++++++++++++++++------------------
62
include/sysemu/blockdev.h | 3 +
47
block/vvfat.c | 43 ++----------------
63
block.c | 2 +-
48
meson.build | 1 +
64
block/backup.c | 20 ++-
49
tests/qemu-iotests/151 | 54 +++++++++++++++++++++-
65
block/blkdebug.c | 2 +-
50
tests/qemu-iotests/151.out | 4 +-
66
block/blklogwrites.c | 7 +-
51
tests/qemu-iotests/307 | 15 ++++++
67
block/blkreplay.c | 2 +-
52
tests/qemu-iotests/307.out | 8 ++++
68
block/block-backend.c | 8 +-
53
11 files changed, 182 insertions(+), 89 deletions(-)
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
54
55
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
2
3
Fleecing scheme works as follows: we want a kind of temporary snapshot
3
This field is unused, but it very helpful for debugging.
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
4
39
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
5
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
40
Reviewed-by: Fam Zheng <famz@redhat.com>
6
Message-Id: <20210702211636.228981-2-vsementsov@virtuozzo.com>
41
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
42
---
8
---
43
block/backup.c | 20 ++++++++++++++------
9
block/mirror.c | 1 +
44
1 file changed, 14 insertions(+), 6 deletions(-)
10
1 file changed, 1 insertion(+)
45
11
46
diff --git a/block/backup.c b/block/backup.c
12
diff --git a/block/mirror.c b/block/mirror.c
47
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
48
--- a/block/backup.c
14
--- a/block/mirror.c
49
+++ b/block/backup.c
15
+++ b/block/mirror.c
50
@@ -XXX,XX +XXX,XX @@ typedef struct BackupBlockJob {
16
@@ -XXX,XX +XXX,XX @@ static MirrorOp *coroutine_fn active_write_prepare(MirrorBlockJob *s,
51
HBitmap *copy_bitmap;
17
.bytes = bytes,
52
bool use_copy_range;
18
.is_active_write = true,
53
int64_t copy_range_size;
19
.is_in_flight = true,
54
+
20
+ .co = qemu_coroutine_self(),
55
+ bool serialize_target_writes;
21
};
56
} BackupBlockJob;
22
qemu_co_queue_init(&op->waiting_requests);
57
23
QTAILQ_INSERT_TAIL(&s->ops_in_flight, op, next);
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
--
24
--
122
2.13.6
25
2.31.1
123
26
124
27
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
2
3
Serialized writes should be used in copy-on-write of backup(sync=none)
3
There is a dead-lock in active mirror: when we have parallel
4
for image fleecing scheme.
4
intersecting requests (note that non intersecting requests may be
5
considered intersecting after aligning to mirror granularity), it may
6
happen that request A waits request B in mirror_wait_on_conflicts() and
7
request B waits for A.
5
8
6
We need to change an assert in bdrv_aligned_pwritev, added in
9
Look at the test for details. Test now dead-locks, that's why it's
7
28de2dcd88de. The assert may fail now, because call to
10
disabled. Next commit will fix mirror and enable the test.
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
11
16
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
12
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
17
Reviewed-by: Fam Zheng <famz@redhat.com>
13
Message-Id: <20210702211636.228981-3-vsementsov@virtuozzo.com>
18
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
19
---
15
---
20
include/block/block.h | 14 +++++++++++++-
16
tests/qemu-iotests/151 | 62 ++++++++++++++++++++++++++++++++++++--
21
block/io.c | 28 +++++++++++++++++++++++++++-
17
tests/qemu-iotests/151.out | 4 +--
22
2 files changed, 40 insertions(+), 2 deletions(-)
18
2 files changed, 62 insertions(+), 4 deletions(-)
23
19
24
diff --git a/include/block/block.h b/include/block/block.h
20
diff --git a/tests/qemu-iotests/151 b/tests/qemu-iotests/151
21
index XXXXXXX..XXXXXXX 100755
22
--- a/tests/qemu-iotests/151
23
+++ b/tests/qemu-iotests/151
24
@@ -XXX,XX +XXX,XX @@ class TestActiveMirror(iotests.QMPTestCase):
25
'if': 'none',
26
'node-name': 'source-node',
27
'driver': iotests.imgfmt,
28
- 'file': {'driver': 'file',
29
- 'filename': source_img}}
30
+ 'file': {'driver': 'blkdebug',
31
+ 'image': {'driver': 'file',
32
+ 'filename': source_img}}}
33
34
blk_target = {'node-name': 'target-node',
35
'driver': iotests.imgfmt,
36
@@ -XXX,XX +XXX,XX @@ class TestActiveMirror(iotests.QMPTestCase):
37
38
self.potential_writes_in_flight = False
39
40
+ def testIntersectingActiveIO(self):
41
+ # FIXME: test-case is dead-locking. To reproduce dead-lock just drop
42
+ # this return statement
43
+ return
44
+
45
+ # Fill the source image
46
+ result = self.vm.hmp_qemu_io('source', 'write -P 1 0 2M')
47
+
48
+ # Start the block job (very slowly)
49
+ result = self.vm.qmp('blockdev-mirror',
50
+ job_id='mirror',
51
+ filter_node_name='mirror-node',
52
+ device='source-node',
53
+ target='target-node',
54
+ sync='full',
55
+ copy_mode='write-blocking',
56
+ speed=1)
57
+
58
+ self.vm.hmp_qemu_io('source', 'break write_aio A')
59
+ self.vm.hmp_qemu_io('source', 'aio_write 0 1M') # 1
60
+ self.vm.hmp_qemu_io('source', 'wait_break A')
61
+ self.vm.hmp_qemu_io('source', 'aio_write 0 2M') # 2
62
+ self.vm.hmp_qemu_io('source', 'aio_write 0 2M') # 3
63
+
64
+ # Now 2 and 3 are in mirror_wait_on_conflicts, waiting for 1
65
+
66
+ self.vm.hmp_qemu_io('source', 'break write_aio B')
67
+ self.vm.hmp_qemu_io('source', 'aio_write 1M 2M') # 4
68
+ self.vm.hmp_qemu_io('source', 'wait_break B')
69
+
70
+ # 4 doesn't wait for 2 and 3, because they didn't yet set
71
+ # in_flight_bitmap. So, nothing prevents 4 to go except for our
72
+ # break-point B.
73
+
74
+ self.vm.hmp_qemu_io('source', 'resume A')
75
+
76
+ # Now we resumed 1, so 2 and 3 goes to the next iteration of while loop
77
+ # in mirror_wait_on_conflicts(). They don't exit, as bitmap is dirty
78
+ # due to request 4. And they start to wait: 2 wait for 3, 3 wait for 2
79
+ # - DEAD LOCK.
80
+ # Note that it's important that we add request 4 at last: requests are
81
+ # appended to the list, so we are sure that 4 is last in the list, so 2
82
+ # and 3 now waits for each other, not for 4.
83
+
84
+ self.vm.hmp_qemu_io('source', 'resume B')
85
+
86
+ # Resuming 4 doesn't help, 2 and 3 already dead-locked
87
+ # To check the dead-lock run:
88
+ # gdb -p $(pidof qemu-system-x86_64) -ex 'set $job=(MirrorBlockJob *)jobs.lh_first' -ex 'p *$job->ops_in_flight.tqh_first' -ex 'p *$job->ops_in_flight.tqh_first->next.tqe_next'
89
+ # You'll see two MirrorOp objects waiting on each other
90
+
91
+ result = self.vm.qmp('block-job-set-speed', device='mirror', speed=0)
92
+ self.assert_qmp(result, 'return', {})
93
+ self.complete_and_wait(drive='mirror')
94
+
95
+ self.potential_writes_in_flight = False
96
+
97
98
if __name__ == '__main__':
99
iotests.main(supported_fmts=['qcow2', 'raw'],
100
diff --git a/tests/qemu-iotests/151.out b/tests/qemu-iotests/151.out
25
index XXXXXXX..XXXXXXX 100644
101
index XXXXXXX..XXXXXXX 100644
26
--- a/include/block/block.h
102
--- a/tests/qemu-iotests/151.out
27
+++ b/include/block/block.h
103
+++ b/tests/qemu-iotests/151.out
28
@@ -XXX,XX +XXX,XX @@ typedef enum {
104
@@ -XXX,XX +XXX,XX @@
29
* content. */
105
-...
30
BDRV_REQ_WRITE_UNCHANGED = 0x40,
106
+....
31
107
----------------------------------------------------------------------
32
+ /*
108
-Ran 3 tests
33
+ * BDRV_REQ_SERIALISING forces request serialisation for writes.
109
+Ran 4 tests
34
+ * It is used to ensure that writes to the backing file of a backup process
110
35
+ * target cannot race with a read of the backup target that defers to the
111
OK
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
--
112
--
119
2.13.6
113
2.31.1
120
114
121
115
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
2
3
Pass read flags and write flags separately. This is needed to handle
3
It's possible that requests start to wait each other in
4
coming BDRV_REQ_NO_SERIALISING clearly in following patches.
4
mirror_wait_on_conflicts(). To avoid it let's use same technique as in
5
block/io.c in bdrv_wait_serialising_requests_locked() /
6
bdrv_find_conflicting_request(): don't wait on intersecting request if
7
it is already waiting for some other request.
5
8
9
For details of the dead-lock look at testIntersectingActiveIO()
10
test-case which we actually fixing now.
11
12
Fixes: d06107ade0ce74dc39739bac80de84b51ec18546
6
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
13
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
7
Reviewed-by: Fam Zheng <famz@redhat.com>
14
Message-Id: <20210702211636.228981-4-vsementsov@virtuozzo.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
16
---
10
include/block/block.h | 3 ++-
17
block/mirror.c | 12 ++++++++++++
11
include/block/block_int.h | 14 +++++++++----
18
tests/qemu-iotests/151 | 18 +++++-------------
12
include/sysemu/block-backend.h | 3 ++-
19
2 files changed, 17 insertions(+), 13 deletions(-)
13
block/backup.c | 2 +-
14
block/block-backend.c | 5 +++--
15
block/file-posix.c | 21 +++++++++++--------
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
20
23
diff --git a/include/block/block.h b/include/block/block.h
21
diff --git a/block/mirror.c b/block/mirror.c
24
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
25
--- a/include/block/block.h
23
--- a/block/mirror.c
26
+++ b/include/block/block.h
24
+++ b/block/mirror.c
27
@@ -XXX,XX +XXX,XX @@ void bdrv_unregister_buf(BlockDriverState *bs, void *host);
25
@@ -XXX,XX +XXX,XX @@ struct MirrorOp {
28
**/
26
bool is_in_flight;
29
int coroutine_fn bdrv_co_copy_range(BdrvChild *src, uint64_t src_offset,
27
CoQueue waiting_requests;
30
BdrvChild *dst, uint64_t dst_offset,
28
Coroutine *co;
31
- uint64_t bytes, BdrvRequestFlags flags);
29
+ MirrorOp *waiting_for_op;
32
+ uint64_t bytes, BdrvRequestFlags read_flags,
30
33
+ BdrvRequestFlags write_flags);
31
QTAILQ_ENTRY(MirrorOp) next;
34
#endif
32
};
35
diff --git a/include/block/block_int.h b/include/block/block_int.h
33
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn mirror_wait_on_conflicts(MirrorOp *self,
36
index XXXXXXX..XXXXXXX 100644
34
if (ranges_overlap(self_start_chunk, self_nb_chunks,
37
--- a/include/block/block_int.h
35
op_start_chunk, op_nb_chunks))
38
+++ b/include/block/block_int.h
36
{
39
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
37
+ /*
40
BdrvChild *dst,
38
+ * If the operation is already (indirectly) waiting for us, or
41
uint64_t dst_offset,
39
+ * will wait for us as soon as it wakes up, then just go on
42
uint64_t bytes,
40
+ * (instead of producing a deadlock in the former case).
43
- BdrvRequestFlags flags);
41
+ */
44
+ BdrvRequestFlags read_flags,
42
+ if (op->waiting_for_op) {
45
+ BdrvRequestFlags write_flags);
43
+ continue;
46
44
+ }
47
/* Map [offset, offset + nbytes) range onto a child of bs to copy data to,
45
+
48
* and invoke bdrv_co_copy_range_to(child, src, ...), or perform the copy
46
+ self->waiting_for_op = op;
49
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
47
qemu_co_queue_wait(&op->waiting_requests, NULL);
50
BdrvChild *dst,
48
+ self->waiting_for_op = NULL;
51
uint64_t dst_offset,
49
break;
52
uint64_t bytes,
50
}
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
}
51
}
201
52
diff --git a/tests/qemu-iotests/151 b/tests/qemu-iotests/151
202
ret = src->bs->drv->bdrv_co_copy_range_from(src->bs,
53
index XXXXXXX..XXXXXXX 100755
203
src, src_offset,
54
--- a/tests/qemu-iotests/151
204
dst, dst_offset,
55
+++ b/tests/qemu-iotests/151
205
- bytes, flags);
56
@@ -XXX,XX +XXX,XX @@ class TestActiveMirror(iotests.QMPTestCase):
206
+ bytes,
57
self.potential_writes_in_flight = False
207
+ read_flags, write_flags);
58
208
59
def testIntersectingActiveIO(self):
209
tracked_request_end(&req);
60
- # FIXME: test-case is dead-locking. To reproduce dead-lock just drop
210
bdrv_dec_in_flight(src->bs);
61
- # this return statement
211
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_co_copy_range_internal(BdrvChild *src,
62
- return
212
tracked_request_begin(&req, dst->bs, dst_offset, bytes,
63
-
213
BDRV_TRACKED_WRITE);
64
# Fill the source image
214
65
result = self.vm.hmp_qemu_io('source', 'write -P 1 0 2M')
215
- /* BDRV_REQ_NO_SERIALISING is only for read operation,
66
216
- * so we ignore it in flags.
67
@@ -XXX,XX +XXX,XX @@ class TestActiveMirror(iotests.QMPTestCase):
217
- */
68
218
+ /* BDRV_REQ_NO_SERIALISING is only for read operation */
69
# Now we resumed 1, so 2 and 3 goes to the next iteration of while loop
219
+ assert(!(write_flags & BDRV_REQ_NO_SERIALISING));
70
# in mirror_wait_on_conflicts(). They don't exit, as bitmap is dirty
220
wait_serialising_requests(&req);
71
- # due to request 4. And they start to wait: 2 wait for 3, 3 wait for 2
221
72
- # - DEAD LOCK.
222
ret = dst->bs->drv->bdrv_co_copy_range_to(dst->bs,
73
- # Note that it's important that we add request 4 at last: requests are
223
src, src_offset,
74
- # appended to the list, so we are sure that 4 is last in the list, so 2
224
dst, dst_offset,
75
- # and 3 now waits for each other, not for 4.
225
- bytes, flags);
76
+ # due to request 4.
226
+ bytes,
77
+ # In the past at that point 2 and 3 would wait for each other producing
227
+ read_flags, write_flags);
78
+ # a dead-lock. Now this is fixed and they will wait for request 4.
228
79
229
tracked_request_end(&req);
80
self.vm.hmp_qemu_io('source', 'resume B')
230
bdrv_dec_in_flight(dst->bs);
81
231
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_co_copy_range_internal(BdrvChild *src,
82
- # Resuming 4 doesn't help, 2 and 3 already dead-locked
232
* semantics. */
83
- # To check the dead-lock run:
233
int coroutine_fn bdrv_co_copy_range_from(BdrvChild *src, uint64_t src_offset,
84
- # gdb -p $(pidof qemu-system-x86_64) -ex 'set $job=(MirrorBlockJob *)jobs.lh_first' -ex 'p *$job->ops_in_flight.tqh_first' -ex 'p *$job->ops_in_flight.tqh_first->next.tqe_next'
234
BdrvChild *dst, uint64_t dst_offset,
85
- # You'll see two MirrorOp objects waiting on each other
235
- uint64_t bytes, BdrvRequestFlags flags)
86
+ # After resuming 4, one of 2 and 3 goes first and set in_flight_bitmap,
236
+ uint64_t bytes,
87
+ # so the other will wait for it.
237
+ BdrvRequestFlags read_flags,
88
238
+ BdrvRequestFlags write_flags)
89
result = self.vm.qmp('block-job-set-speed', device='mirror', speed=0)
239
{
90
self.assert_qmp(result, 'return', {})
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
302
index XXXXXXX..XXXXXXX 100644
303
--- a/block/qcow2.c
304
+++ b/block/qcow2.c
305
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn
306
qcow2_co_copy_range_from(BlockDriverState *bs,
307
BdrvChild *src, uint64_t src_offset,
308
BdrvChild *dst, uint64_t dst_offset,
309
- uint64_t bytes, BdrvRequestFlags flags)
310
+ uint64_t bytes, BdrvRequestFlags read_flags,
311
+ BdrvRequestFlags write_flags)
312
{
313
BDRVQcow2State *s = bs->opaque;
314
int ret;
315
unsigned int cur_bytes; /* number of bytes in current iteration */
316
BdrvChild *child = NULL;
317
- BdrvRequestFlags cur_flags;
318
+ BdrvRequestFlags cur_write_flags;
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
}
407
return bdrv_co_copy_range_from(bs->file, src_offset, dst, dst_offset,
408
- bytes, flags);
409
+ bytes, read_flags, write_flags);
410
}
411
412
static int coroutine_fn raw_co_copy_range_to(BlockDriverState *bs,
413
- BdrvChild *src, uint64_t src_offset,
414
- BdrvChild *dst, uint64_t dst_offset,
415
- uint64_t bytes, BdrvRequestFlags flags)
416
+ BdrvChild *src,
417
+ uint64_t src_offset,
418
+ BdrvChild *dst,
419
+ uint64_t dst_offset,
420
+ uint64_t bytes,
421
+ BdrvRequestFlags read_flags,
422
+ BdrvRequestFlags write_flags)
423
{
424
int ret;
425
426
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn raw_co_copy_range_to(BlockDriverState *bs,
427
return ret;
428
}
429
return bdrv_co_copy_range_to(src, src_offset, bs->file, dst_offset, bytes,
430
- flags);
431
+ read_flags, write_flags);
432
}
433
434
BlockDriver bdrv_raw = {
435
diff --git a/qemu-img.c b/qemu-img.c
436
index XXXXXXX..XXXXXXX 100644
437
--- a/qemu-img.c
438
+++ b/qemu-img.c
439
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn convert_co_copy_range(ImgConvertState *s, int64_t sector
440
441
ret = blk_co_copy_range(blk, offset, s->target,
442
sector_num << BDRV_SECTOR_BITS,
443
- n << BDRV_SECTOR_BITS, 0);
444
+ n << BDRV_SECTOR_BITS, 0, 0);
445
if (ret < 0) {
446
return ret;
447
}
448
--
91
--
449
2.13.6
92
2.31.1
450
93
451
94
diff view generated by jsdifflib
1
Commit dcf94a23b1 ('block: Don't poll in parent drain callbacks')
1
Currently, the block driver whitelists are only applied for the system
2
removed polling in bdrv_child_cb_drained_begin() on the grounds that the
2
emulator. All other binaries still give unrestricted access to all block
3
original bdrv_drain() already will poll and BdrvChildRole.drained_begin
3
drivers. There are use cases where this made sense because the main
4
calls must not cause graph changes (and therefore must not call
4
concern was avoiding customers running VMs on less optimised block
5
aio_poll() or the recursion through the graph will break.
5
drivers and getting bad performance. Allowing the same image format e.g.
6
as a target for 'qemu-img convert' is not a problem then.
6
7
7
This reasoning is correct for calls through bdrv_do_drained_begin().
8
However, if the concern is the supportability of the driver in general,
8
However, BdrvChildRole.drained_begin is also called when a node that is
9
either in full or when used read-write, not applying the list driver
9
already in a drained section (i.e. bdrv_do_drained_begin() has already
10
whitelist in tools doesn't help - especially since qemu-nbd and
10
returned and therefore can't poll any more) is attached to a new parent.
11
qemu-storage-daemon now give access to more or less the same operations
11
In this case, we must explicitly poll to have all requests completed
12
in block drivers as running a system emulator.
12
before the drained new child can be attached to the parent.
13
13
14
In bdrv_replace_child_noperm(), we know that we're not inside the
14
In order to address this, introduce a new configure option that enforces
15
recursion of bdrv_do_drained_begin() because graph changes are not
15
the driver whitelist in all binaries.
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
16
20
Reported-by: Max Reitz <mreitz@redhat.com>
17
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
18
Message-Id: <20210709164141.254097-1-kwolf@redhat.com>
19
Reviewed-by: Eric Blake <eblake@redhat.com>
21
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
20
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
22
---
21
---
23
include/block/block.h | 8 ++++++++
22
configure | 14 ++++++++++++--
24
include/block/block_int.h | 3 +++
23
block.c | 3 +++
25
block.c | 2 +-
24
meson.build | 1 +
26
block/io.c | 26 ++++++++++++++++++++------
25
3 files changed, 16 insertions(+), 2 deletions(-)
27
4 files changed, 32 insertions(+), 7 deletions(-)
28
26
29
diff --git a/include/block/block.h b/include/block/block.h
27
diff --git a/configure b/configure
30
index XXXXXXX..XXXXXXX 100644
28
index XXXXXXX..XXXXXXX 100755
31
--- a/include/block/block.h
29
--- a/configure
32
+++ b/include/block/block.h
30
+++ b/configure
33
@@ -XXX,XX +XXX,XX @@ void bdrv_parent_drained_begin(BlockDriverState *bs, BdrvChild *ignore,
31
@@ -XXX,XX +XXX,XX @@ cross_prefix=""
34
bool ignore_bds_parents);
32
audio_drv_list=""
35
33
block_drv_rw_whitelist=""
36
/**
34
block_drv_ro_whitelist=""
37
+ * bdrv_parent_drained_begin_single:
35
+block_drv_whitelist_tools="no"
38
+ *
36
host_cc="cc"
39
+ * Begin a quiesced section for the parent of @c. If @poll is true, wait for
37
audio_win_int=""
40
+ * any pending activity to cease.
38
libs_qga=""
41
+ */
39
@@ -XXX,XX +XXX,XX @@ for opt do
42
+void bdrv_parent_drained_begin_single(BdrvChild *c, bool poll);
40
;;
43
+
41
--block-drv-ro-whitelist=*) block_drv_ro_whitelist=$(echo "$optarg" | sed -e 's/,/ /g')
44
+/**
42
;;
45
* bdrv_parent_drained_end:
43
+ --enable-block-drv-whitelist-in-tools) block_drv_whitelist_tools="yes"
46
*
44
+ ;;
47
* End a quiesced section of all users of @bs. This is part of
45
+ --disable-block-drv-whitelist-in-tools) block_drv_whitelist_tools="no"
48
diff --git a/include/block/block_int.h b/include/block/block_int.h
46
+ ;;
49
index XXXXXXX..XXXXXXX 100644
47
--enable-debug-tcg) debug_tcg="yes"
50
--- a/include/block/block_int.h
48
;;
51
+++ b/include/block/block_int.h
49
--disable-debug-tcg) debug_tcg="no"
52
@@ -XXX,XX +XXX,XX @@ struct BdrvChildRole {
50
@@ -XXX,XX +XXX,XX @@ Advanced options (experts only):
53
* requests after returning from .drained_begin() until .drained_end() is
51
--block-drv-whitelist=L Same as --block-drv-rw-whitelist=L
54
* called.
52
--block-drv-rw-whitelist=L
55
*
53
set block driver read-write whitelist
56
+ * These functions must not change the graph (and therefore also must not
54
- (affects only QEMU, not qemu-img)
57
+ * call aio_poll(), which could change the graph indirectly).
55
+ (by default affects only QEMU, not tools like qemu-img)
58
+ *
56
--block-drv-ro-whitelist=L
59
* Note that this can be nested. If drained_begin() was called twice, new
57
set block driver read-only whitelist
60
* I/O is allowed only after drained_end() was called twice, too.
58
- (affects only QEMU, not qemu-img)
61
*/
59
+ (by default affects only QEMU, not tools like qemu-img)
60
+ --enable-block-drv-whitelist-in-tools
61
+ use block whitelist also in tools instead of only QEMU
62
--enable-trace-backends=B Set trace backend
63
Available backends: $trace_backend_list
64
--with-trace-file=NAME Full PATH,NAME of file to store traces
65
@@ -XXX,XX +XXX,XX @@ if test "$audio_win_int" = "yes" ; then
66
fi
67
echo "CONFIG_BDRV_RW_WHITELIST=$block_drv_rw_whitelist" >> $config_host_mak
68
echo "CONFIG_BDRV_RO_WHITELIST=$block_drv_ro_whitelist" >> $config_host_mak
69
+if test "$block_drv_whitelist_tools" = "yes" ; then
70
+ echo "CONFIG_BDRV_WHITELIST_TOOLS=y" >> $config_host_mak
71
+fi
72
if test "$xfs" = "yes" ; then
73
echo "CONFIG_XFS=y" >> $config_host_mak
74
fi
62
diff --git a/block.c b/block.c
75
diff --git a/block.c b/block.c
63
index XXXXXXX..XXXXXXX 100644
76
index XXXXXXX..XXXXXXX 100644
64
--- a/block.c
77
--- a/block.c
65
+++ b/block.c
78
+++ b/block.c
66
@@ -XXX,XX +XXX,XX @@ static void bdrv_replace_child_noperm(BdrvChild *child,
79
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs,
67
}
80
68
assert(num >= 0);
81
void bdrv_init(void)
69
for (i = 0; i < num; i++) {
82
{
70
- child->role->drained_begin(child);
83
+#ifdef CONFIG_BDRV_WHITELIST_TOOLS
71
+ bdrv_parent_drained_begin_single(child, true);
84
+ use_bdrv_whitelist = 1;
72
}
85
+#endif
73
}
86
module_call_init(MODULE_INIT_BLOCK);
74
87
}
75
diff --git a/block/io.c b/block/io.c
88
89
diff --git a/meson.build b/meson.build
76
index XXXXXXX..XXXXXXX 100644
90
index XXXXXXX..XXXXXXX 100644
77
--- a/block/io.c
91
--- a/meson.build
78
+++ b/block/io.c
92
+++ b/meson.build
79
@@ -XXX,XX +XXX,XX @@ void bdrv_parent_drained_begin(BlockDriverState *bs, BdrvChild *ignore,
93
@@ -XXX,XX +XXX,XX @@ summary_info += {'coroutine pool': config_host['CONFIG_COROUTINE_POOL'] == '1
80
if (c == ignore || (ignore_bds_parents && c->role->parent_is_bds)) {
94
if have_block
81
continue;
95
summary_info += {'Block whitelist (rw)': config_host['CONFIG_BDRV_RW_WHITELIST']}
82
}
96
summary_info += {'Block whitelist (ro)': config_host['CONFIG_BDRV_RO_WHITELIST']}
83
- if (c->role->drained_begin) {
97
+ summary_info += {'Use block whitelist in tools': config_host.has_key('CONFIG_BDRV_WHITELIST_TOOLS')}
84
- c->role->drained_begin(c);
98
summary_info += {'VirtFS support': have_virtfs}
85
- }
99
summary_info += {'build virtiofs daemon': have_virtiofsd}
86
+ bdrv_parent_drained_begin_single(c, false);
100
summary_info += {'Live block migration': config_host.has_key('CONFIG_LIVE_BLOCK_MIGRATION')}
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
--
101
--
132
2.13.6
102
2.31.1
133
103
134
104
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
1
From: Cornelia Huck <cohuck@redhat.com>
1
From: Lukas Straub <lukasstraub2@web.de>
2
2
3
This reverts commit b0083267444a5e0f28391f6c2831a539f878d424.
3
s->active_disk is bs->file. Remove it and use local variables instead.
4
4
5
Hold off removing this for one more QEMU release (current libvirt
5
Signed-off-by: Lukas Straub <lukasstraub2@web.de>
6
release still uses it.)
6
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
7
7
Message-Id: <2534f867ea9be5b666dfce19744b7d4e2b96c976.1626619393.git.lukasstraub2@web.de>
8
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
8
Reviewed-by: Zhang Chen <chen.zhang@intel.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
10
---
11
include/hw/block/block.h | 1 +
11
block/replication.c | 34 +++++++++++++++++-----------------
12
include/sysemu/blockdev.h | 1 +
12
1 file changed, 17 insertions(+), 17 deletions(-)
13
block/block-backend.c | 1 +
14
blockdev.c | 10 ++++++++++
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
13
27
diff --git a/include/hw/block/block.h b/include/hw/block/block.h
14
diff --git a/block/replication.c b/block/replication.c
28
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
29
--- a/include/hw/block/block.h
16
--- a/block/replication.c
30
+++ b/include/hw/block/block.h
17
+++ b/block/replication.c
31
@@ -XXX,XX +XXX,XX @@ static inline unsigned int get_physical_block_exp(BlockConf *conf)
18
@@ -XXX,XX +XXX,XX @@ typedef enum {
32
19
typedef struct BDRVReplicationState {
33
/* Configuration helpers */
20
ReplicationMode mode;
34
21
ReplicationStage stage;
35
+void blkconf_serial(BlockConf *conf, char **serial);
22
- BdrvChild *active_disk;
36
bool blkconf_geometry(BlockConf *conf, int *trans,
23
BlockJob *commit_job;
37
unsigned cyls_max, unsigned heads_max, unsigned secs_max,
24
BdrvChild *hidden_disk;
38
Error **errp);
25
BdrvChild *secondary_disk;
39
diff --git a/include/sysemu/blockdev.h b/include/sysemu/blockdev.h
26
@@ -XXX,XX +XXX,XX @@ out:
40
index XXXXXXX..XXXXXXX 100644
27
return ret;
41
--- a/include/sysemu/blockdev.h
28
}
42
+++ b/include/sysemu/blockdev.h
29
43
@@ -XXX,XX +XXX,XX @@ struct DriveInfo {
30
-static void secondary_do_checkpoint(BDRVReplicationState *s, Error **errp)
44
bool is_default; /* Added by default_drive() ? */
31
+static void secondary_do_checkpoint(BlockDriverState *bs, Error **errp)
45
int media_cd;
32
{
46
QemuOpts *opts;
33
+ BDRVReplicationState *s = bs->opaque;
47
+ char *serial;
34
+ BdrvChild *active_disk = bs->file;
48
QTAILQ_ENTRY(DriveInfo) next;
35
Error *local_err = NULL;
49
};
36
int ret;
50
37
51
diff --git a/block/block-backend.c b/block/block-backend.c
38
@@ -XXX,XX +XXX,XX @@ static void secondary_do_checkpoint(BDRVReplicationState *s, Error **errp)
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;
39
return;
57
}
40
}
58
qemu_opts_del(dinfo->opts);
41
59
+ g_free(dinfo->serial);
42
- if (!s->active_disk->bs->drv) {
60
g_free(dinfo);
43
+ if (!active_disk->bs->drv) {
61
}
44
error_setg(errp, "Active disk %s is ejected",
62
45
- s->active_disk->bs->node_name);
63
diff --git a/blockdev.c b/blockdev.c
46
+ active_disk->bs->node_name);
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
+{
119
+ DriveInfo *dinfo;
120
+
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
+}
129
+
130
void blkconf_blocksizes(BlockConf *conf)
131
{
132
BlockBackend *blk = conf->blk;
133
diff --git a/hw/block/nvme.c b/hw/block/nvme.c
134
index XXXXXXX..XXXXXXX 100644
135
--- a/hw/block/nvme.c
136
+++ b/hw/block/nvme.c
137
@@ -XXX,XX +XXX,XX @@ static void nvme_realize(PCIDevice *pci_dev, Error **errp)
138
return;
47
return;
139
}
48
}
140
49
141
+ blkconf_serial(&n->conf, &n->serial);
50
- ret = bdrv_make_empty(s->active_disk, errp);
142
if (!n->serial) {
51
+ ret = bdrv_make_empty(active_disk, errp);
143
error_setg(errp, "serial property not set");
52
if (ret < 0) {
144
return;
145
diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
146
index XXXXXXX..XXXXXXX 100644
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;
53
return;
151
}
54
}
152
55
@@ -XXX,XX +XXX,XX @@ static void replication_start(ReplicationState *rs, ReplicationMode mode,
153
+ blkconf_serial(&conf->conf, &conf->serial);
56
BlockDriverState *bs = rs->opaque;
154
if (!blkconf_apply_backend_options(&conf->conf,
57
BDRVReplicationState *s;
155
blk_is_read_only(conf->conf.blk), true,
58
BlockDriverState *top_bs;
156
errp)) {
59
+ BdrvChild *active_disk;
157
diff --git a/hw/ide/qdev.c b/hw/ide/qdev.c
60
int64_t active_length, hidden_length, disk_length;
158
index XXXXXXX..XXXXXXX 100644
61
AioContext *aio_context;
159
--- a/hw/ide/qdev.c
62
Error *local_err = NULL;
160
+++ b/hw/ide/qdev.c
63
@@ -XXX,XX +XXX,XX @@ static void replication_start(ReplicationState *rs, ReplicationMode mode,
161
@@ -XXX,XX +XXX,XX @@ static void ide_dev_initfn(IDEDevice *dev, IDEDriveKind kind, Error **errp)
64
case REPLICATION_MODE_PRIMARY:
162
return;
65
break;
66
case REPLICATION_MODE_SECONDARY:
67
- s->active_disk = bs->file;
68
- if (!s->active_disk || !s->active_disk->bs ||
69
- !s->active_disk->bs->backing) {
70
+ active_disk = bs->file;
71
+ if (!active_disk || !active_disk->bs || !active_disk->bs->backing) {
72
error_setg(errp, "Active disk doesn't have backing file");
73
aio_context_release(aio_context);
74
return;
75
}
76
77
- s->hidden_disk = s->active_disk->bs->backing;
78
+ s->hidden_disk = active_disk->bs->backing;
79
if (!s->hidden_disk->bs || !s->hidden_disk->bs->backing) {
80
error_setg(errp, "Hidden disk doesn't have backing file");
81
aio_context_release(aio_context);
82
@@ -XXX,XX +XXX,XX @@ static void replication_start(ReplicationState *rs, ReplicationMode mode,
83
}
84
85
/* verify the length */
86
- active_length = bdrv_getlength(s->active_disk->bs);
87
+ active_length = bdrv_getlength(active_disk->bs);
88
hidden_length = bdrv_getlength(s->hidden_disk->bs);
89
disk_length = bdrv_getlength(s->secondary_disk->bs);
90
if (active_length < 0 || hidden_length < 0 || disk_length < 0 ||
91
@@ -XXX,XX +XXX,XX @@ static void replication_start(ReplicationState *rs, ReplicationMode mode,
92
}
93
94
/* Must be true, or the bdrv_getlength() calls would have failed */
95
- assert(s->active_disk->bs->drv && s->hidden_disk->bs->drv);
96
+ assert(active_disk->bs->drv && s->hidden_disk->bs->drv);
97
98
- if (!s->active_disk->bs->drv->bdrv_make_empty ||
99
+ if (!active_disk->bs->drv->bdrv_make_empty ||
100
!s->hidden_disk->bs->drv->bdrv_make_empty) {
101
error_setg(errp,
102
"Active disk or hidden disk doesn't support make_empty");
103
@@ -XXX,XX +XXX,XX @@ static void replication_start(ReplicationState *rs, ReplicationMode mode,
104
s->stage = BLOCK_REPLICATION_RUNNING;
105
106
if (s->mode == REPLICATION_MODE_SECONDARY) {
107
- secondary_do_checkpoint(s, errp);
108
+ secondary_do_checkpoint(bs, errp);
163
}
109
}
164
110
165
+ blkconf_serial(&dev->conf, &dev->serial);
111
s->error = 0;
166
if (kind != IDE_CD) {
112
@@ -XXX,XX +XXX,XX @@ static void replication_do_checkpoint(ReplicationState *rs, Error **errp)
167
if (!blkconf_geometry(&dev->conf, &dev->chs_trans, 65535, 16, 255,
168
errp)) {
169
diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c
170
index XXXXXXX..XXXXXXX 100644
171
--- a/hw/scsi/scsi-disk.c
172
+++ b/hw/scsi/scsi-disk.c
173
@@ -XXX,XX +XXX,XX @@ static void scsi_realize(SCSIDevice *dev, Error **errp)
174
return;
175
}
113
}
176
114
177
+ blkconf_serial(&s->qdev.conf, &s->serial);
115
if (s->mode == REPLICATION_MODE_SECONDARY) {
178
blkconf_blocksizes(&s->qdev.conf);
116
- secondary_do_checkpoint(s, errp);
179
117
+ secondary_do_checkpoint(bs, errp);
180
if (s->qdev.conf.logical_block_size >
181
diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c
182
index XXXXXXX..XXXXXXX 100644
183
--- a/hw/usb/dev-storage.c
184
+++ b/hw/usb/dev-storage.c
185
@@ -XXX,XX +XXX,XX @@ static void usb_msd_storage_realize(USBDevice *dev, Error **errp)
186
return;
187
}
118
}
188
119
aio_context_release(aio_context);
189
+ blkconf_serial(&s->conf, &dev->serial);
190
blkconf_blocksizes(&s->conf);
191
if (!blkconf_apply_backend_options(&s->conf, blk_is_read_only(blk), true,
192
errp)) {
193
diff --git a/tests/ahci-test.c b/tests/ahci-test.c
194
index XXXXXXX..XXXXXXX 100644
195
--- a/tests/ahci-test.c
196
+++ b/tests/ahci-test.c
197
@@ -XXX,XX +XXX,XX @@ static AHCIQState *ahci_boot(const char *cli, ...)
198
s = ahci_vboot(cli, ap);
199
va_end(ap);
200
} else {
201
- cli = "-drive if=none,id=drive0,file=%s,cache=writeback,format=%s"
202
+ cli = "-drive if=none,id=drive0,file=%s,cache=writeback,serial=%s"
203
+ ",format=%s"
204
" -M q35 "
205
"-device ide-hd,drive=drive0 "
206
- "-global ide-hd.serial=%s "
207
"-global ide-hd.ver=%s";
208
- s = ahci_boot(cli, tmp_path, imgfmt, "testdisk", "version");
209
+ s = ahci_boot(cli, tmp_path, "testdisk", imgfmt, "version");
210
}
211
212
return s;
213
diff --git a/tests/ide-test.c b/tests/ide-test.c
214
index XXXXXXX..XXXXXXX 100644
215
--- a/tests/ide-test.c
216
+++ b/tests/ide-test.c
217
@@ -XXX,XX +XXX,XX @@ static void test_bmdma_no_busmaster(void)
218
static void test_bmdma_setup(void)
219
{
220
ide_test_start(
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
}
120
}
228
@@ -XXX,XX +XXX,XX @@ static void test_identify(void)
121
@@ -XXX,XX +XXX,XX @@ static void replication_done(void *opaque, int ret)
229
int ret;
122
if (ret == 0) {
230
123
s->stage = BLOCK_REPLICATION_DONE;
231
ide_test_start(
124
232
- "-drive file=%s,if=ide,cache=writeback,format=raw "
125
- s->active_disk = NULL;
233
- "-global ide-hd.serial=%s -global ide-hd.ver=%s",
126
s->secondary_disk = NULL;
234
+ "-drive file=%s,if=ide,serial=%s,cache=writeback,format=raw "
127
s->hidden_disk = NULL;
235
+ "-global ide-hd.ver=%s",
128
s->error = 0;
236
tmp_path, "testdisk", "version");
129
@@ -XXX,XX +XXX,XX @@ static void replication_stop(ReplicationState *rs, bool failover, Error **errp)
237
130
}
238
dev = get_pci_device(&bmdma_bar, &ide_bar);
131
239
diff --git a/qemu-doc.texi b/qemu-doc.texi
132
if (!failover) {
240
index XXXXXXX..XXXXXXX 100644
133
- secondary_do_checkpoint(s, errp);
241
--- a/qemu-doc.texi
134
+ secondary_do_checkpoint(bs, errp);
242
+++ b/qemu-doc.texi
135
s->stage = BLOCK_REPLICATION_DONE;
243
@@ -XXX,XX +XXX,XX @@ with ``-device ...,netdev=x''), or ``-nic user,smb=/some/dir''
136
aio_context_release(aio_context);
244
(for embedded NICs). The new syntax allows different settings to be
137
return;
245
provided per NIC.
138
@@ -XXX,XX +XXX,XX @@ static void replication_stop(ReplicationState *rs, bool failover, Error **errp)
246
139
247
+@subsection -drive serial=... (since 2.10.0)
140
s->stage = BLOCK_REPLICATION_FAILOVER;
248
+
141
s->commit_job = commit_active_start(
249
+The drive serial argument is replaced by the the serial argument
142
- NULL, s->active_disk->bs, s->secondary_disk->bs,
250
+that can be specified with the ``-device'' parameter.
143
+ NULL, bs->file->bs, s->secondary_disk->bs,
251
+
144
JOB_INTERNAL, 0, BLOCKDEV_ON_ERROR_REPORT,
252
@subsection -usbdevice (since 2.10.0)
145
NULL, replication_done, bs, true, errp);
253
146
break;
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
--
147
--
280
2.13.6
148
2.31.1
281
149
282
150
diff view generated by jsdifflib
1
From: Fam Zheng <famz@redhat.com>
1
From: Lukas Straub <lukasstraub2@web.de>
2
2
3
Other I/O functions are already using a BdrvChild pointer in the API, so
3
In preparation for the next patch, initialize s->hidden_disk and
4
make discard do the same. It makes it possible to initiate the same
4
s->secondary_disk later and replace access to them with local variables
5
permission checks before doing I/O, and much easier to share the
5
in the places where they aren't initialized yet.
6
helper functions for this, which will be added and used by write,
7
truncate and copy range paths.
8
6
9
Signed-off-by: Fam Zheng <famz@redhat.com>
7
Signed-off-by: Lukas Straub <lukasstraub2@web.de>
8
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
9
Message-Id: <1eb9dc179267207d9c7eccaeb30761758e32e9ab.1626619393.git.lukasstraub2@web.de>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
---
11
---
12
include/block/block.h | 4 ++--
12
block/replication.c | 45 ++++++++++++++++++++++++++++-----------------
13
block/blkdebug.c | 2 +-
13
1 file changed, 28 insertions(+), 17 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
14
25
diff --git a/include/block/block.h b/include/block/block.h
15
diff --git a/block/replication.c b/block/replication.c
26
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
27
--- a/include/block/block.h
17
--- a/block/replication.c
28
+++ b/include/block/block.h
18
+++ b/block/replication.c
29
@@ -XXX,XX +XXX,XX @@ AioWait *bdrv_get_aio_wait(BlockDriverState *bs);
19
@@ -XXX,XX +XXX,XX @@ static void reopen_backing_file(BlockDriverState *bs, bool writable,
30
bdrv_get_aio_context(bs_), \
20
Error **errp)
31
cond); })
21
{
32
22
BDRVReplicationState *s = bs->opaque;
33
-int bdrv_pdiscard(BlockDriverState *bs, int64_t offset, int bytes);
23
+ BdrvChild *hidden_disk, *secondary_disk;
34
-int bdrv_co_pdiscard(BlockDriverState *bs, int64_t offset, int bytes);
24
BlockReopenQueue *reopen_queue = NULL;
35
+int bdrv_pdiscard(BdrvChild *child, int64_t offset, int bytes);
25
36
+int bdrv_co_pdiscard(BdrvChild *child, int64_t offset, int bytes);
26
+ /*
37
int bdrv_has_zero_init_1(BlockDriverState *bs);
27
+ * s->hidden_disk and s->secondary_disk may not be set yet, as they will
38
int bdrv_has_zero_init(BlockDriverState *bs);
28
+ * only be set after the children are writable.
39
bool bdrv_unallocated_blocks_are_zero(BlockDriverState *bs);
29
+ */
40
diff --git a/block/blkdebug.c b/block/blkdebug.c
30
+ hidden_disk = bs->file->bs->backing;
41
index XXXXXXX..XXXXXXX 100644
31
+ secondary_disk = hidden_disk->bs->backing;
42
--- a/block/blkdebug.c
32
+
43
+++ b/block/blkdebug.c
33
if (writable) {
44
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn blkdebug_co_pdiscard(BlockDriverState *bs,
34
- s->orig_hidden_read_only = bdrv_is_read_only(s->hidden_disk->bs);
45
return err;
35
- s->orig_secondary_read_only = bdrv_is_read_only(s->secondary_disk->bs);
36
+ s->orig_hidden_read_only = bdrv_is_read_only(hidden_disk->bs);
37
+ s->orig_secondary_read_only = bdrv_is_read_only(secondary_disk->bs);
46
}
38
}
47
39
48
- return bdrv_co_pdiscard(bs->file->bs, offset, bytes);
40
- bdrv_subtree_drained_begin(s->hidden_disk->bs);
49
+ return bdrv_co_pdiscard(bs->file, offset, bytes);
41
- bdrv_subtree_drained_begin(s->secondary_disk->bs);
42
+ bdrv_subtree_drained_begin(hidden_disk->bs);
43
+ bdrv_subtree_drained_begin(secondary_disk->bs);
44
45
if (s->orig_hidden_read_only) {
46
QDict *opts = qdict_new();
47
qdict_put_bool(opts, BDRV_OPT_READ_ONLY, !writable);
48
- reopen_queue = bdrv_reopen_queue(reopen_queue, s->hidden_disk->bs,
49
+ reopen_queue = bdrv_reopen_queue(reopen_queue, hidden_disk->bs,
50
opts, true);
51
}
52
53
if (s->orig_secondary_read_only) {
54
QDict *opts = qdict_new();
55
qdict_put_bool(opts, BDRV_OPT_READ_ONLY, !writable);
56
- reopen_queue = bdrv_reopen_queue(reopen_queue, s->secondary_disk->bs,
57
+ reopen_queue = bdrv_reopen_queue(reopen_queue, secondary_disk->bs,
58
opts, true);
59
}
60
61
@@ -XXX,XX +XXX,XX @@ static void reopen_backing_file(BlockDriverState *bs, bool writable,
62
}
63
}
64
65
- bdrv_subtree_drained_end(s->hidden_disk->bs);
66
- bdrv_subtree_drained_end(s->secondary_disk->bs);
67
+ bdrv_subtree_drained_end(hidden_disk->bs);
68
+ bdrv_subtree_drained_end(secondary_disk->bs);
50
}
69
}
51
70
52
static int coroutine_fn blkdebug_co_block_status(BlockDriverState *bs,
71
static void backup_job_cleanup(BlockDriverState *bs)
53
diff --git a/block/blklogwrites.c b/block/blklogwrites.c
72
@@ -XXX,XX +XXX,XX @@ static void replication_start(ReplicationState *rs, ReplicationMode mode,
54
index XXXXXXX..XXXXXXX 100644
73
BlockDriverState *bs = rs->opaque;
55
--- a/block/blklogwrites.c
74
BDRVReplicationState *s;
56
+++ b/block/blklogwrites.c
75
BlockDriverState *top_bs;
57
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn blk_log_writes_co_do_file_flush(BlkLogWritesFileReq *fr)
76
- BdrvChild *active_disk;
58
static int coroutine_fn
77
+ BdrvChild *active_disk, *hidden_disk, *secondary_disk;
59
blk_log_writes_co_do_file_pdiscard(BlkLogWritesFileReq *fr)
78
int64_t active_length, hidden_length, disk_length;
60
{
79
AioContext *aio_context;
61
- return bdrv_co_pdiscard(fr->bs->file->bs, fr->offset, fr->bytes);
80
Error *local_err = NULL;
62
+ return bdrv_co_pdiscard(fr->bs->file, fr->offset, fr->bytes);
81
@@ -XXX,XX +XXX,XX @@ static void replication_start(ReplicationState *rs, ReplicationMode mode,
63
}
82
return;
64
65
static int coroutine_fn
66
diff --git a/block/blkreplay.c b/block/blkreplay.c
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
{
73
uint64_t reqid = blkreplay_next_id();
74
- int ret = bdrv_co_pdiscard(bs->file->bs, offset, bytes);
75
+ int ret = bdrv_co_pdiscard(bs->file, offset, bytes);
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
}
90
91
int blk_co_flush(BlockBackend *blk)
92
diff --git a/block/copy-on-read.c b/block/copy-on-read.c
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
{
100
- return bdrv_co_pdiscard(bs->file->bs, offset, bytes);
101
+ return bdrv_co_pdiscard(bs->file, offset, bytes);
102
}
103
104
105
diff --git a/block/io.c b/block/io.c
106
index XXXXXXX..XXXXXXX 100644
107
--- a/block/io.c
108
+++ b/block/io.c
109
@@ -XXX,XX +XXX,XX @@ int bdrv_flush(BlockDriverState *bs)
110
}
111
112
typedef struct DiscardCo {
113
- BlockDriverState *bs;
114
+ BdrvChild *child;
115
int64_t offset;
116
int bytes;
117
int ret;
118
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn bdrv_pdiscard_co_entry(void *opaque)
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
}
83
}
189
84
190
g_free(d);
85
- s->hidden_disk = active_disk->bs->backing;
191
diff --git a/block/raw-format.c b/block/raw-format.c
86
- if (!s->hidden_disk->bs || !s->hidden_disk->bs->backing) {
192
index XXXXXXX..XXXXXXX 100644
87
+ hidden_disk = active_disk->bs->backing;
193
--- a/block/raw-format.c
88
+ if (!hidden_disk->bs || !hidden_disk->bs->backing) {
194
+++ b/block/raw-format.c
89
error_setg(errp, "Hidden disk doesn't have backing file");
195
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn raw_co_pdiscard(BlockDriverState *bs,
90
aio_context_release(aio_context);
196
if (ret) {
91
return;
197
return ret;
92
}
198
}
93
199
- return bdrv_co_pdiscard(bs->file->bs, offset, bytes);
94
- s->secondary_disk = s->hidden_disk->bs->backing;
200
+ return bdrv_co_pdiscard(bs->file, offset, bytes);
95
- if (!s->secondary_disk->bs || !bdrv_has_blk(s->secondary_disk->bs)) {
201
}
96
+ secondary_disk = hidden_disk->bs->backing;
202
97
+ if (!secondary_disk->bs || !bdrv_has_blk(secondary_disk->bs)) {
203
static int64_t raw_getlength(BlockDriverState *bs)
98
error_setg(errp, "The secondary disk doesn't have block backend");
204
diff --git a/block/throttle.c b/block/throttle.c
99
aio_context_release(aio_context);
205
index XXXXXXX..XXXXXXX 100644
100
return;
206
--- a/block/throttle.c
101
@@ -XXX,XX +XXX,XX @@ static void replication_start(ReplicationState *rs, ReplicationMode mode,
207
+++ b/block/throttle.c
102
208
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn throttle_co_pdiscard(BlockDriverState *bs,
103
/* verify the length */
209
ThrottleGroupMember *tgm = bs->opaque;
104
active_length = bdrv_getlength(active_disk->bs);
210
throttle_group_co_io_limits_intercept(tgm, bytes, true);
105
- hidden_length = bdrv_getlength(s->hidden_disk->bs);
211
106
- disk_length = bdrv_getlength(s->secondary_disk->bs);
212
- return bdrv_co_pdiscard(bs->file->bs, offset, bytes);
107
+ hidden_length = bdrv_getlength(hidden_disk->bs);
213
+ return bdrv_co_pdiscard(bs->file, offset, bytes);
108
+ disk_length = bdrv_getlength(secondary_disk->bs);
214
}
109
if (active_length < 0 || hidden_length < 0 || disk_length < 0 ||
215
110
active_length != hidden_length || hidden_length != disk_length) {
216
static int throttle_co_flush(BlockDriverState *bs)
111
error_setg(errp, "Active disk, hidden disk, secondary disk's length"
112
@@ -XXX,XX +XXX,XX @@ static void replication_start(ReplicationState *rs, ReplicationMode mode,
113
}
114
115
/* Must be true, or the bdrv_getlength() calls would have failed */
116
- assert(active_disk->bs->drv && s->hidden_disk->bs->drv);
117
+ assert(active_disk->bs->drv && hidden_disk->bs->drv);
118
119
if (!active_disk->bs->drv->bdrv_make_empty ||
120
- !s->hidden_disk->bs->drv->bdrv_make_empty) {
121
+ !hidden_disk->bs->drv->bdrv_make_empty) {
122
error_setg(errp,
123
"Active disk or hidden disk doesn't support make_empty");
124
aio_context_release(aio_context);
125
@@ -XXX,XX +XXX,XX @@ static void replication_start(ReplicationState *rs, ReplicationMode mode,
126
return;
127
}
128
129
+ s->hidden_disk = hidden_disk;
130
+ s->secondary_disk = secondary_disk;
131
+
132
/* start backup job now */
133
error_setg(&s->blocker,
134
"Block device is in use by internal backup job");
217
--
135
--
218
2.13.6
136
2.31.1
219
137
220
138
diff view generated by jsdifflib
1
If the virtual disk size isn't aligned to full clusters,
1
From: Lukas Straub <lukasstraub2@web.de>
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
2
5
qemu-io: block/io.c:1203: bdrv_co_do_copy_on_readv: Assertion `skip_bytes < pnum' failed.
3
The replication driver needs access to the children block-nodes of
4
it's child so it can issue bdrv_make_empty() and bdrv_co_pwritev()
5
to manage the replication. However, it does this by directly copying
6
the BdrvChilds, which is wrong.
6
7
7
Check for EOF, assert that we read at least as much as the read request
8
Fix this by properly attaching the block-nodes with
8
originally wanted to have (which is true at EOF because otherwise
9
bdrv_attach_child() and requesting the required permissions.
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
10
11
This ultimatively fixes a potential crash in replication_co_writev(),
12
because it may write to s->secondary_disk if it is in state
13
BLOCK_REPLICATION_FAILOVER_FAILED, without requesting write
14
permissions first. And now the workaround in
15
secondary_do_checkpoint() can be removed.
16
17
Signed-off-by: Lukas Straub <lukasstraub2@web.de>
18
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
19
Message-Id: <5d0539d729afb8072d0d7cde977c5066285591b4.1626619393.git.lukasstraub2@web.de>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
20
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
---
21
---
14
block/io.c | 6 ++++++
22
block/replication.c | 30 +++++++++++++++++++++++++++---
15
tests/qemu-iotests/197 | 9 +++++++++
23
1 file changed, 27 insertions(+), 3 deletions(-)
16
tests/qemu-iotests/197.out | 8 ++++++++
17
3 files changed, 23 insertions(+)
18
24
19
diff --git a/block/io.c b/block/io.c
25
diff --git a/block/replication.c b/block/replication.c
20
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
21
--- a/block/io.c
27
--- a/block/replication.c
22
+++ b/block/io.c
28
+++ b/block/replication.c
23
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_co_do_copy_on_readv(BdrvChild *child,
29
@@ -XXX,XX +XXX,XX @@ static void replication_child_perm(BlockDriverState *bs, BdrvChild *c,
24
pnum = MIN(cluster_bytes, max_transfer);
30
uint64_t perm, uint64_t shared,
31
uint64_t *nperm, uint64_t *nshared)
32
{
33
- *nperm = BLK_PERM_CONSISTENT_READ;
34
+ if (role & BDRV_CHILD_PRIMARY) {
35
+ *nperm = BLK_PERM_CONSISTENT_READ;
36
+ } else {
37
+ *nperm = 0;
38
+ }
39
+
40
if ((bs->open_flags & (BDRV_O_INACTIVE | BDRV_O_RDWR)) == BDRV_O_RDWR) {
41
*nperm |= BLK_PERM_WRITE;
42
}
43
@@ -XXX,XX +XXX,XX @@ static void replication_start(ReplicationState *rs, ReplicationMode mode,
44
return;
25
}
45
}
26
46
27
+ /* Stop at EOF if the image ends in the middle of the cluster */
47
- s->hidden_disk = hidden_disk;
28
+ if (ret == 0 && pnum == 0) {
48
- s->secondary_disk = secondary_disk;
29
+ assert(progress >= bytes);
49
+ bdrv_ref(hidden_disk->bs);
30
+ break;
50
+ s->hidden_disk = bdrv_attach_child(bs, hidden_disk->bs, "hidden disk",
51
+ &child_of_bds, BDRV_CHILD_DATA,
52
+ &local_err);
53
+ if (local_err) {
54
+ error_propagate(errp, local_err);
55
+ aio_context_release(aio_context);
56
+ return;
31
+ }
57
+ }
32
+
58
+
33
assert(skip_bytes < pnum);
59
+ bdrv_ref(secondary_disk->bs);
34
60
+ s->secondary_disk = bdrv_attach_child(bs, secondary_disk->bs,
35
if (ret <= 0) {
61
+ "secondary disk", &child_of_bds,
36
diff --git a/tests/qemu-iotests/197 b/tests/qemu-iotests/197
62
+ BDRV_CHILD_DATA, &local_err);
37
index XXXXXXX..XXXXXXX 100755
63
+ if (local_err) {
38
--- a/tests/qemu-iotests/197
64
+ error_propagate(errp, local_err);
39
+++ b/tests/qemu-iotests/197
65
+ aio_context_release(aio_context);
40
@@ -XXX,XX +XXX,XX @@ $QEMU_IO -f qcow2 -c map "$TEST_WRAP"
66
+ return;
41
_check_test_img
67
+ }
42
$QEMU_IMG compare -f $IMGFMT -F qcow2 "$TEST_IMG" "$TEST_WRAP"
68
43
69
/* start backup job now */
44
+echo
70
error_setg(&s->blocker,
45
+echo '=== Partial final cluster ==='
71
@@ -XXX,XX +XXX,XX @@ static void replication_done(void *opaque, int ret)
46
+echo
72
if (ret == 0) {
47
+
73
s->stage = BLOCK_REPLICATION_DONE;
48
+_make_test_img 1024
74
49
+$QEMU_IO -f $IMGFMT -C -c 'read 0 1024' "$TEST_IMG" | _filter_qemu_io
75
+ bdrv_unref_child(bs, s->secondary_disk);
50
+$QEMU_IO -f $IMGFMT -c map "$TEST_IMG"
76
s->secondary_disk = NULL;
51
+_check_test_img
77
+ bdrv_unref_child(bs, s->hidden_disk);
52
+
78
s->hidden_disk = NULL;
53
# success, all done
79
s->error = 0;
54
echo '*** done'
80
} else {
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
--
81
--
74
2.13.6
82
2.31.1
75
83
76
84
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
1
From: Fam Zheng <famz@redhat.com>
1
From: Lukas Straub <lukasstraub2@web.de>
2
2
3
Truncation is the last to convert from open coded req handling to
3
Remove the workaround introduced in commit
4
reusing helpers. This time the permission check in prepare has to adapt
4
6ecbc6c52672db5c13805735ca02784879ce8285
5
to the new caller: it checks a different permission bit, and doesn't
5
"replication: Avoid blk_make_empty() on read-only child".
6
trigger the before write notifier.
7
6
8
Also, truncation should always trigger a bs->total_sectors update and in
7
It is not needed anymore since s->hidden_disk is guaranteed to be
9
turn call parent resize_cb. Update the condition in finish helper, too.
8
writable when secondary_do_checkpoint() runs. Because replication_start(),
9
_do_checkpoint() and _stop() are only called by COLO migration code
10
and COLO-migration activates all disks via bdrv_invalidate_cache_all()
11
before it calls these functions.
10
12
11
It's intended to do a duplicated bs->read_only check before calling
13
Signed-off-by: Lukas Straub <lukasstraub2@web.de>
12
bdrv_co_write_req_prepare() so that we can be more informative with the
14
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
13
error message, as bdrv_co_write_req_prepare() doesn't have Error
15
Message-Id: <d3acfad43879e9f376bffa7dd797ae74d0a7c81a.1626619393.git.lukasstraub2@web.de>
14
parameter.
15
16
Signed-off-by: Fam Zheng <famz@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
block/replication.c | 12 +-----------
20
1 file changed, 35 insertions(+), 20 deletions(-)
19
1 file changed, 1 insertion(+), 11 deletions(-)
21
20
22
diff --git a/block/io.c b/block/io.c
21
diff --git a/block/replication.c b/block/replication.c
23
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
24
--- a/block/io.c
23
--- a/block/replication.c
25
+++ b/block/io.c
24
+++ b/block/replication.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 secondary_do_checkpoint(BlockDriverState *bs, Error **errp)
27
is_request_serialising_and_aligned(req));
26
return;
28
assert(req->overlap_offset <= offset);
29
assert(offset + bytes <= req->overlap_offset + req->overlap_bytes);
30
+ assert(end_sector <= bs->total_sectors || child->perm & BLK_PERM_RESIZE);
31
32
- if (flags & BDRV_REQ_WRITE_UNCHANGED) {
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 {
42
+ assert(child->perm & BLK_PERM_WRITE);
43
+ }
44
+ return notifier_with_return_list_notify(&bs->before_write_notifiers,
45
+ req);
46
+ case BDRV_TRACKED_TRUNCATE:
47
+ assert(child->perm & BLK_PERM_RESIZE);
48
+ return 0;
49
+ default:
50
+ abort();
51
}
27
}
52
- assert(end_sector <= bs->total_sectors || child->perm & BLK_PERM_RESIZE);
28
53
- return notifier_with_return_list_notify(&bs->before_write_notifiers, req);
29
- BlockBackend *blk = blk_new(qemu_get_current_aio_context(),
54
}
30
- BLK_PERM_WRITE, BLK_PERM_ALL);
55
31
- blk_insert_bs(blk, s->hidden_disk->bs, &local_err);
56
static inline void coroutine_fn
32
- if (local_err) {
57
@@ -XXX,XX +XXX,XX @@ bdrv_co_write_req_finish(BdrvChild *child, int64_t offset, uint64_t bytes,
33
- error_propagate(errp, local_err);
58
* beyond EOF cannot expand the image anyway.
34
- blk_unref(blk);
59
*/
35
- return;
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
- }
36
- }
106
-
37
-
107
- assert(!(bs->open_flags & BDRV_O_INACTIVE));
38
- ret = blk_make_empty(blk, errp);
108
39
- blk_unref(blk);
109
ret = drv->bdrv_co_truncate(bs, offset, prealloc, errp);
40
+ ret = bdrv_make_empty(s->hidden_disk, errp);
110
if (ret < 0) {
41
if (ret < 0) {
111
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset,
42
return;
112
} else {
113
offset = bs->total_sectors * BDRV_SECTOR_SIZE;
114
}
43
}
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
--
44
--
126
2.13.6
45
2.31.1
127
46
128
47
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
2
3
Here two things are fixed:
3
Most probably this fake backing child doesn't work anyway (see notes
4
about it in a8a4d15c1c34d).
4
5
5
1. Architecture
6
Still, since 25f78d9e2de528473d52 drivers are required to set
7
.supports_backing if they want to call bdrv_set_backing_hd, so now
8
vvfat just doesn't work because of this check.
6
9
7
On each recursion step, we go to the child of src or dst, only for one
10
Let's finally drop this fake backing file.
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
11
2. Wait for serializing requests on write path independently of
12
Fixes: 25f78d9e2de528473d52acfcf7acdfb64e3453d4
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>
13
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
25
Reviewed-by: Fam Zheng <famz@redhat.com>
14
Message-Id: <20210715124853.13335-1-vsementsov@virtuozzo.com>
15
Tested-by: John Arbuckle <programmingkidx@gmail.com>
26
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
16
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
27
---
17
---
28
include/block/block.h | 12 ++++++++++++
18
block/vvfat.c | 43 ++++---------------------------------------
29
block/io.c | 42 +++++++++++++++++++++++++++---------------
19
1 file changed, 4 insertions(+), 39 deletions(-)
30
2 files changed, 39 insertions(+), 15 deletions(-)
31
20
32
diff --git a/include/block/block.h b/include/block/block.h
21
diff --git a/block/vvfat.c b/block/vvfat.c
33
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
34
--- a/include/block/block.h
23
--- a/block/vvfat.c
35
+++ b/include/block/block.h
24
+++ b/block/vvfat.c
36
@@ -XXX,XX +XXX,XX @@ typedef enum {
25
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vvfat_co_block_status(BlockDriverState *bs,
37
* opened with BDRV_O_UNMAP.
26
return BDRV_BLOCK_DATA;
38
*/
27
}
39
BDRV_REQ_MAY_UNMAP = 0x4,
28
40
+
29
-static int coroutine_fn
41
+ /*
30
-write_target_commit(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
42
+ * The BDRV_REQ_NO_SERIALISING flag is only valid for reads and means that
31
- QEMUIOVector *qiov, int flags)
43
+ * we don't want wait_serialising_requests() during the read operation.
32
-{
44
+ *
33
- int ret;
45
+ * This flag is used for backup copy-on-write operations, when we need to
34
-
46
+ * read old data before write (write notifier triggered). It is okay since
35
- BDRVVVFATState* s = *((BDRVVVFATState**) bs->opaque);
47
+ * we already waited for other serializing requests in the initiating write
36
- qemu_co_mutex_lock(&s->lock);
48
+ * (see bdrv_aligned_pwritev), and it is necessary if the initiating write
37
- ret = try_commit(s);
49
+ * is already serializing (without the flag, the read would deadlock
38
- qemu_co_mutex_unlock(&s->lock);
50
+ * waiting for the serialising write to complete).
39
-
51
+ */
40
- return ret;
52
BDRV_REQ_NO_SERIALISING = 0x8,
41
-}
53
BDRV_REQ_FUA = 0x10,
42
-
54
BDRV_REQ_WRITE_COMPRESSED = 0x20,
43
-static BlockDriver vvfat_write_target = {
55
diff --git a/block/io.c b/block/io.c
44
- .format_name = "vvfat_write_target",
56
index XXXXXXX..XXXXXXX 100644
45
- .instance_size = sizeof(void*),
57
--- a/block/io.c
46
- .bdrv_co_pwritev = write_target_commit,
58
+++ b/block/io.c
47
-};
59
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_aligned_pwritev(BdrvChild *child,
48
-
60
max_transfer = QEMU_ALIGN_DOWN(MIN_NON_ZERO(bs->bl.max_transfer, INT_MAX),
49
static void vvfat_qcow_options(BdrvChildRole role, bool parent_is_format,
61
align);
50
int *child_flags, QDict *child_options,
62
51
int parent_flags, QDict *parent_options)
63
+ /* BDRV_REQ_NO_SERIALISING is only for read operation */
52
@@ -XXX,XX +XXX,XX @@ static int enable_write_target(BlockDriverState *bs, Error **errp)
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
{
53
{
72
- BdrvTrackedRequest src_req, dst_req;
54
BDRVVVFATState *s = bs->opaque;
73
+ BdrvTrackedRequest req;
55
BlockDriver *bdrv_qcow = NULL;
56
- BlockDriverState *backing;
57
QemuOpts *opts = NULL;
74
int ret;
58
int ret;
75
59
int size = sector2cluster(s, s->sector_count);
76
if (!dst || !dst->bs) {
60
@@ -XXX,XX +XXX,XX @@ static int enable_write_target(BlockDriverState *bs, Error **errp)
77
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_co_copy_range_internal(BdrvChild *src,
61
unlink(s->qcow_filename);
78
|| src->bs->encrypted || dst->bs->encrypted) {
62
#endif
79
return -ENOTSUP;
63
80
}
64
- backing = bdrv_new_open_driver(&vvfat_write_target, NULL, BDRV_O_ALLOW_RDWR,
81
- bdrv_inc_in_flight(src->bs);
65
- &error_abort);
82
- bdrv_inc_in_flight(dst->bs);
66
- *(void**) backing->opaque = s;
83
- tracked_request_begin(&src_req, src->bs, src_offset,
67
-
84
- bytes, BDRV_TRACKED_READ);
68
- bdrv_set_backing_hd(s->bs, backing, &error_abort);
85
- tracked_request_begin(&dst_req, dst->bs, dst_offset,
69
- bdrv_unref(backing);
86
- bytes, BDRV_TRACKED_WRITE);
70
-
87
71
return 0;
88
- if (!(flags & BDRV_REQ_NO_SERIALISING)) {
72
89
- wait_serialising_requests(&src_req);
73
err:
90
- wait_serialising_requests(&dst_req);
74
@@ -XXX,XX +XXX,XX @@ static void vvfat_child_perm(BlockDriverState *bs, BdrvChild *c,
75
uint64_t perm, uint64_t shared,
76
uint64_t *nperm, uint64_t *nshared)
77
{
78
- if (role & BDRV_CHILD_DATA) {
79
- /* This is a private node, nobody should try to attach to it */
80
- *nperm = BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE;
81
- *nshared = BLK_PERM_WRITE_UNCHANGED;
82
- } else {
83
- assert(role & BDRV_CHILD_COW);
84
- /* The backing file is there so 'commit' can use it. vvfat doesn't
85
- * access it in any way. */
86
- *nperm = 0;
87
- *nshared = BLK_PERM_ALL;
91
- }
88
- }
92
if (recurse_src) {
89
+ assert(role & BDRV_CHILD_DATA);
93
+ bdrv_inc_in_flight(src->bs);
90
+ /* This is a private node, nobody should try to attach to it */
94
+ tracked_request_begin(&req, src->bs, src_offset, bytes,
91
+ *nperm = BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE;
95
+ BDRV_TRACKED_READ);
92
+ *nshared = BLK_PERM_WRITE_UNCHANGED;
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
}
93
}
133
94
95
static void vvfat_close(BlockDriverState *bs)
134
--
96
--
135
2.13.6
97
2.31.1
136
98
137
99
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
1
From: Ari Sundholm <ari@tuxera.com>
1
From: Max Reitz <mreitz@redhat.com>
2
2
3
The sector size needs to be large enough to accommodate the data
3
When invoking block-export-add with some iothread and
4
structures for the log super block and log write entries. This was
4
fixed-iothread=false, and changing the node's iothread fails, the error
5
previously not properly checked, which made it possible to cause
5
is supposed to be ignored.
6
QEMU to badly misbehave.
7
6
8
Signed-off-by: Ari Sundholm <ari@tuxera.com>
7
However, it is still stored in *errp, which is wrong. If a second error
8
occurs, the "*errp must be NULL" assertion in error_setv() fails:
9
10
qemu-system-x86_64: ../util/error.c:59: error_setv: Assertion
11
`*errp == NULL' failed.
12
13
So if fixed-iothread=false, we should ignore the error by passing NULL
14
to bdrv_try_set_aio_context().
15
16
Fixes: f51d23c80af73c95e0ce703ad06a300f1b3d63ef
17
("block/export: add iothread and fixed-iothread options")
18
Signed-off-by: Max Reitz <mreitz@redhat.com>
19
Message-Id: <20210624083825.29224-2-mreitz@redhat.com>
20
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
21
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
22
---
11
block/blklogwrites.c | 5 ++++-
23
block/export/export.c | 5 ++++-
12
1 file changed, 4 insertions(+), 1 deletion(-)
24
1 file changed, 4 insertions(+), 1 deletion(-)
13
25
14
diff --git a/block/blklogwrites.c b/block/blklogwrites.c
26
diff --git a/block/export/export.c b/block/export/export.c
15
index XXXXXXX..XXXXXXX 100644
27
index XXXXXXX..XXXXXXX 100644
16
--- a/block/blklogwrites.c
28
--- a/block/export/export.c
17
+++ b/block/blklogwrites.c
29
+++ b/block/export/export.c
18
@@ -XXX,XX +XXX,XX @@ static inline uint32_t blk_log_writes_log2(uint32_t value)
30
@@ -XXX,XX +XXX,XX @@ BlockExport *blk_exp_add(BlockExportOptions *export, Error **errp)
19
31
if (export->has_iothread) {
20
static inline bool blk_log_writes_sector_size_valid(uint32_t sector_size)
32
IOThread *iothread;
21
{
33
AioContext *new_ctx;
22
- return sector_size < (1ull << 24) && is_power_of_2(sector_size);
34
+ Error **set_context_errp;
23
+ return is_power_of_2(sector_size) &&
35
24
+ sector_size >= sizeof(struct log_write_super) &&
36
iothread = iothread_by_id(export->iothread);
25
+ sector_size >= sizeof(struct log_write_entry) &&
37
if (!iothread) {
26
+ sector_size < (1ull << 24);
38
@@ -XXX,XX +XXX,XX @@ BlockExport *blk_exp_add(BlockExportOptions *export, Error **errp)
27
}
39
28
40
new_ctx = iothread_get_aio_context(iothread);
29
static uint64_t blk_log_writes_find_cur_log_sector(BdrvChild *log,
41
42
- ret = bdrv_try_set_aio_context(bs, new_ctx, errp);
43
+ /* Ignore errors with fixed-iothread=false */
44
+ set_context_errp = fixed_iothread ? errp : NULL;
45
+ ret = bdrv_try_set_aio_context(bs, new_ctx, set_context_errp);
46
if (ret == 0) {
47
aio_context_release(ctx);
48
aio_context_acquire(new_ctx);
30
--
49
--
31
2.13.6
50
2.31.1
32
51
33
52
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
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
1
From: Fam Zheng <famz@redhat.com>
1
From: Max Reitz <mreitz@redhat.com>
2
2
3
If we are growing the image and potentially using preallocation for the
3
Passing fixed-iothread=true should make iothread conflicts fatal,
4
new area, we need to make sure that no write requests are made to the
4
whereas fixed-iothread=false should not.
5
"preallocated" area which is [@old_size, @offset), not
6
[@offset, offset * 2 - @old_size).
7
5
8
Signed-off-by: Fam Zheng <famz@redhat.com>
6
Combine the second case with an error condition that is checked after
9
Reviewed-by: Eric Blake <eblake@redhat.com>
7
the iothread is handled, to verify that qemu does not crash if there is
8
such an error after changing the iothread failed.
9
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
Message-Id: <20210624083825.29224-3-mreitz@redhat.com>
12
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
13
Tested-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
---
15
---
12
block/io.c | 3 ++-
16
tests/qemu-iotests/307 | 15 +++++++++++++++
13
1 file changed, 2 insertions(+), 1 deletion(-)
17
tests/qemu-iotests/307.out | 8 ++++++++
18
2 files changed, 23 insertions(+)
14
19
15
diff --git a/block/io.c b/block/io.c
20
diff --git a/tests/qemu-iotests/307 b/tests/qemu-iotests/307
21
index XXXXXXX..XXXXXXX 100755
22
--- a/tests/qemu-iotests/307
23
+++ b/tests/qemu-iotests/307
24
@@ -XXX,XX +XXX,XX @@ with iotests.FilePath('image') as img, \
25
iotests.log('=== Launch VM ===')
26
27
vm.add_object('iothread,id=iothread0')
28
+ vm.add_object('iothread,id=iothread1')
29
vm.add_blockdev(f'file,filename={img},node-name=file')
30
vm.add_blockdev(f'{iotests.imgfmt},file=file,node-name=fmt')
31
vm.add_blockdev('raw,file=file,node-name=ro,read-only=on')
32
+ vm.add_blockdev('null-co,node-name=null')
33
vm.add_device(f'id=scsi0,driver=virtio-scsi,iothread=iothread0')
34
vm.launch()
35
36
@@ -XXX,XX +XXX,XX @@ with iotests.FilePath('image') as img, \
37
vm.qmp_log('query-block-exports')
38
iotests.qemu_nbd_list_log('-k', socket)
39
40
+ iotests.log('\n=== Add export with conflicting iothread ===')
41
+
42
+ vm.qmp_log('device_add', id='sdb', driver='scsi-hd', drive='null')
43
+
44
+ # Should fail because of fixed-iothread
45
+ vm.qmp_log('block-export-add', id='export1', type='nbd', node_name='null',
46
+ iothread='iothread1', fixed_iothread=True, writable=True)
47
+
48
+ # Should ignore the iothread conflict, but then fail because of the
49
+ # permission conflict (and not crash)
50
+ vm.qmp_log('block-export-add', id='export1', type='nbd', node_name='null',
51
+ iothread='iothread1', fixed_iothread=False, writable=True)
52
+
53
iotests.log('\n=== Add a writable export ===')
54
55
# This fails because share-rw=off
56
diff --git a/tests/qemu-iotests/307.out b/tests/qemu-iotests/307.out
16
index XXXXXXX..XXXXXXX 100644
57
index XXXXXXX..XXXXXXX 100644
17
--- a/block/io.c
58
--- a/tests/qemu-iotests/307.out
18
+++ b/block/io.c
59
+++ b/tests/qemu-iotests/307.out
19
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset,
60
@@ -XXX,XX +XXX,XX @@ exports available: 1
20
}
61
base:allocation
21
62
22
bdrv_inc_in_flight(bs);
63
23
- tracked_request_begin(&req, bs, offset, new_bytes, BDRV_TRACKED_TRUNCATE);
64
+=== Add export with conflicting iothread ===
24
+ tracked_request_begin(&req, bs, offset - new_bytes, new_bytes,
65
+{"execute": "device_add", "arguments": {"drive": "null", "driver": "scsi-hd", "id": "sdb"}}
25
+ BDRV_TRACKED_TRUNCATE);
66
+{"return": {}}
26
67
+{"execute": "block-export-add", "arguments": {"fixed-iothread": true, "id": "export1", "iothread": "iothread1", "node-name": "null", "type": "nbd", "writable": true}}
27
/* If we are growing the image and potentially using preallocation for the
68
+{"error": {"class": "GenericError", "desc": "Cannot change iothread of active block backend"}}
28
* new area, we need to make sure that no write requests are made to it
69
+{"execute": "block-export-add", "arguments": {"fixed-iothread": false, "id": "export1", "iothread": "iothread1", "node-name": "null", "type": "nbd", "writable": true}}
70
+{"error": {"class": "GenericError", "desc": "Permission conflict on node 'null': permissions 'write' are both required by an unnamed block device (uses node 'null' as 'root' child) and unshared by block device 'sdb' (uses node 'null' as 'root' child)."}}
71
+
72
=== Add a writable export ===
73
{"execute": "block-export-add", "arguments": {"description": "This is the writable second export", "id": "export1", "name": "export1", "node-name": "fmt", "type": "nbd", "writable": true, "writethrough": true}}
74
{"error": {"class": "GenericError", "desc": "Permission conflict on node 'fmt': permissions 'write' are both required by an unnamed block device (uses node 'fmt' as 'root' child) and unshared by block device 'sda' (uses node 'fmt' as 'root' child)."}}
29
--
75
--
30
2.13.6
76
2.31.1
31
77
32
78
diff view generated by jsdifflib