1
The following changes since commit e47f81b617684c4546af286d307b69014a83538a:
1
The following changes since commit 8cb41fda78c7ebde0dd248c6afe1d336efb0de50:
2
2
3
Merge remote-tracking branch 'remotes/thibault/tags/samuel-thibault' into staging (2019-02-07 18:53:25 +0000)
3
Merge remote-tracking branch 'remotes/philmd/tags/machine-20211101' into staging (2021-11-02 05:53:45 -0400)
4
4
5
are available in the Git repository at:
5
are available in the Git repository at:
6
6
7
git://github.com/stefanha/qemu.git tags/block-pull-request
7
https://github.com/XanClic/qemu.git tags/pull-block-2021-11-02
8
8
9
for you to fetch changes up to 55140166667bb555c5d05165b93b25557d2e6397:
9
for you to fetch changes up to 7da9623cc078229caf07c290e16401ccdb9408d2:
10
10
11
tests/virtio-blk: add test for WRITE_ZEROES command (2019-02-11 11:58:17 +0800)
11
block/vpc: Add a sanity check that fixed-size images have the right type (2021-11-02 12:47:51 +0100)
12
12
13
----------------------------------------------------------------
13
----------------------------------------------------------------
14
Pull request
14
Emanuele Giuseppe Esposito (1):
15
pylint: fix errors and warnings generated by tests/qemu-iotests/297
15
16
16
User-visible changes:
17
Eric Blake (1):
18
qemu-img: Consistent docs for convert -F
17
19
18
* virtio-blk: DISCARD and WRITE_ZEROES support
20
Thomas Huth (1):
21
block/vpc: Add a sanity check that fixed-size images have the right
22
type
19
23
20
----------------------------------------------------------------
24
Thomas Weißschuh (1):
25
vmdk: allow specification of tools version
21
26
22
Peter Xu (1):
27
docs/tools/qemu-img.rst | 2 +-
23
iothread: fix iothread hang when stop too soon
28
qapi/block-core.json | 3 +++
24
29
block/vmdk.c | 24 ++++++++++++++++++++----
25
Stefano Garzarella (7):
30
block/vpc.c | 3 ++-
26
virtio-blk: cleanup using VirtIOBlock *s and VirtIODevice *vdev
31
qemu-img-cmds.hx | 2 +-
27
virtio-blk: add acct_failed param to virtio_blk_handle_rw_error()
32
tests/qemu-iotests/129 | 18 +++++++++---------
28
virtio-blk: add host_features field in VirtIOBlock
33
tests/qemu-iotests/310 | 16 ++++++++--------
29
virtio-blk: add "discard" and "write-zeroes" properties
34
tests/qemu-iotests/check | 11 ++++++-----
30
virtio-blk: add DISCARD and WRITE_ZEROES features
35
tests/qemu-iotests/iotests.py | 7 ++++---
31
tests/virtio-blk: change assert on data_size in virtio_blk_request()
36
tests/qemu-iotests/tests/image-fleecing | 4 ++--
32
tests/virtio-blk: add test for WRITE_ZEROES command
37
10 files changed, 56 insertions(+), 34 deletions(-)
33
34
Vladimir Sementsov-Ogievskiy (1):
35
qemugdb/coroutine: fix arch_prctl has unknown return type
36
37
include/hw/virtio/virtio-blk.h | 5 +-
38
hw/block/virtio-blk.c | 236 +++++++++++++++++++++++++++++----
39
hw/core/machine.c | 2 +
40
iothread.c | 6 +-
41
tests/virtio-blk-test.c | 75 ++++++++++-
42
scripts/qemugdb/coroutine.py | 2 +-
43
6 files changed, 297 insertions(+), 29 deletions(-)
44
38
45
--
39
--
46
2.20.1
40
2.31.1
47
41
48
42
diff view generated by jsdifflib
Deleted patch
1
From: Peter Xu <peterx@redhat.com>
2
1
3
Lukas reported an hard to reproduce QMP iothread hang on s390 that
4
QEMU might hang at pthread_join() of the QMP monitor iothread before
5
quitting:
6
7
Thread 1
8
#0 0x000003ffad10932c in pthread_join
9
#1 0x0000000109e95750 in qemu_thread_join
10
at /home/thuth/devel/qemu/util/qemu-thread-posix.c:570
11
#2 0x0000000109c95a1c in iothread_stop
12
#3 0x0000000109bb0874 in monitor_cleanup
13
#4 0x0000000109b55042 in main
14
15
While the iothread is still in the main loop:
16
17
Thread 4
18
#0 0x000003ffad0010e4 in ??
19
#1 0x000003ffad553958 in g_main_context_iterate.isra.19
20
#2 0x000003ffad553d90 in g_main_loop_run
21
#3 0x0000000109c9585a in iothread_run
22
at /home/thuth/devel/qemu/iothread.c:74
23
#4 0x0000000109e94752 in qemu_thread_start
24
at /home/thuth/devel/qemu/util/qemu-thread-posix.c:502
25
#5 0x000003ffad10825a in start_thread
26
#6 0x000003ffad00dcf2 in thread_start
27
28
IMHO it's because there's a race between the main thread and iothread
29
when stopping the thread in following sequence:
30
31
main thread iothread
32
=========== ==============
33
aio_poll()
34
iothread_get_g_main_context
35
set iothread->worker_context
36
iothread_stop
37
schedule iothread_stop_bh
38
execute iothread_stop_bh [1]
39
set iothread->running=false
40
(since main_loop==NULL so
41
skip to quit main loop.
42
Note: although main_loop is
43
NULL but worker_context is
44
not!)
45
atomic_read(&iothread->worker_context) [2]
46
create main_loop object
47
g_main_loop_run() [3]
48
pthread_join() [4]
49
50
We can see that when execute iothread_stop_bh() at [1] it's possible
51
that main_loop is still NULL because it's only created until the first
52
check of the worker_context later at [2]. Then the iothread will hang
53
in the main loop [3] and it'll starve the main thread too [4].
54
55
Here the simple solution should be that we check again the "running"
56
variable before check against worker_context.
57
58
CC: Thomas Huth <thuth@redhat.com>
59
CC: Dr. David Alan Gilbert <dgilbert@redhat.com>
60
CC: Stefan Hajnoczi <stefanha@redhat.com>
61
CC: Lukáš Doktor <ldoktor@redhat.com>
62
CC: Markus Armbruster <armbru@redhat.com>
63
CC: Eric Blake <eblake@redhat.com>
64
CC: Paolo Bonzini <pbonzini@redhat.com>
65
Reported-by: Lukáš Doktor <ldoktor@redhat.com>
66
Signed-off-by: Peter Xu <peterx@redhat.com>
67
Tested-by: Thomas Huth <thuth@redhat.com>
68
Message-id: 20190129051432.22023-1-peterx@redhat.com
69
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
70
---
71
iothread.c | 6 +++++-
72
1 file changed, 5 insertions(+), 1 deletion(-)
73
74
diff --git a/iothread.c b/iothread.c
75
index XXXXXXX..XXXXXXX 100644
76
--- a/iothread.c
77
+++ b/iothread.c
78
@@ -XXX,XX +XXX,XX @@ static void *iothread_run(void *opaque)
79
while (iothread->running) {
80
aio_poll(iothread->ctx, true);
81
82
- if (atomic_read(&iothread->worker_context)) {
83
+ /*
84
+ * We must check the running state again in case it was
85
+ * changed in previous aio_poll()
86
+ */
87
+ if (iothread->running && atomic_read(&iothread->worker_context)) {
88
GMainLoop *loop;
89
90
g_main_context_push_thread_default(iothread->worker_context);
91
--
92
2.20.1
93
94
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
qemu coroutine command results in following error output:
4
5
Python Exception <class 'gdb.error'> 'arch_prctl' has unknown return
6
type; cast the call to its declared return type: Error occurred in
7
Python command: 'arch_prctl' has unknown return type; cast the call to
8
its declared return type
9
10
Fix it by giving it what it wants: arch_prctl return type.
11
12
Information on the topic:
13
https://sourceware.org/gdb/onlinedocs/gdb/Calling.html
14
15
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
16
Message-id: 20190206151425.105871-1-vsementsov@virtuozzo.com
17
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
18
---
19
scripts/qemugdb/coroutine.py | 2 +-
20
1 file changed, 1 insertion(+), 1 deletion(-)
21
22
diff --git a/scripts/qemugdb/coroutine.py b/scripts/qemugdb/coroutine.py
23
index XXXXXXX..XXXXXXX 100644
24
--- a/scripts/qemugdb/coroutine.py
25
+++ b/scripts/qemugdb/coroutine.py
26
@@ -XXX,XX +XXX,XX @@ def get_fs_base():
27
pthread_self().'''
28
# %rsp - 120 is scratch space according to the SystemV ABI
29
old = gdb.parse_and_eval('*(uint64_t*)($rsp - 120)')
30
- gdb.execute('call arch_prctl(0x1003, $rsp - 120)', False, True)
31
+ gdb.execute('call (int)arch_prctl(0x1003, $rsp - 120)', False, True)
32
fs_base = gdb.parse_and_eval('*(uint64_t*)($rsp - 120)')
33
gdb.execute('set *(uint64_t*)($rsp - 120) = %s' % old, False, True)
34
return fs_base
35
--
36
2.20.1
37
38
diff view generated by jsdifflib
Deleted patch
1
From: Stefano Garzarella <sgarzare@redhat.com>
2
1
3
In several part we still using req->dev or VIRTIO_DEVICE(req->dev)
4
when we have already defined s and vdev pointers:
5
VirtIOBlock *s = req->dev;
6
VirtIODevice *vdev = VIRTIO_DEVICE(s);
7
8
Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
9
Reviewed-by: Liam Merwick <liam.merwick@oracle.com>
10
Message-id: 20190208142347.214815-1-sgarzare@redhat.com
11
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
12
---
13
hw/block/virtio-blk.c | 22 +++++++++-------------
14
1 file changed, 9 insertions(+), 13 deletions(-)
15
16
diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/block/virtio-blk.c
19
+++ b/hw/block/virtio-blk.c
20
@@ -XXX,XX +XXX,XX @@ static void virtio_blk_req_complete(VirtIOBlockReq *req, unsigned char status)
21
static int virtio_blk_handle_rw_error(VirtIOBlockReq *req, int error,
22
bool is_read)
23
{
24
- BlockErrorAction action = blk_get_error_action(req->dev->blk,
25
- is_read, error);
26
VirtIOBlock *s = req->dev;
27
+ BlockErrorAction action = blk_get_error_action(s->blk, is_read, error);
28
29
if (action == BLOCK_ERROR_ACTION_STOP) {
30
/* Break the link as the next request is going to be parsed from the
31
@@ -XXX,XX +XXX,XX @@ static void virtio_blk_flush_complete(void *opaque, int ret)
32
}
33
34
virtio_blk_req_complete(req, VIRTIO_BLK_S_OK);
35
- block_acct_done(blk_get_stats(req->dev->blk), &req->acct);
36
+ block_acct_done(blk_get_stats(s->blk), &req->acct);
37
virtio_blk_free_request(req);
38
39
out:
40
@@ -XXX,XX +XXX,XX @@ static int virtio_blk_handle_request(VirtIOBlockReq *req, MultiReqBuffer *mrb)
41
- sizeof(struct virtio_blk_inhdr);
42
iov_discard_back(in_iov, &in_num, sizeof(struct virtio_blk_inhdr));
43
44
- type = virtio_ldl_p(VIRTIO_DEVICE(req->dev), &req->out.type);
45
+ type = virtio_ldl_p(vdev, &req->out.type);
46
47
/* VIRTIO_BLK_T_OUT defines the command direction. VIRTIO_BLK_T_BARRIER
48
* is an optional flag. Although a guest should not send this flag if
49
@@ -XXX,XX +XXX,XX @@ static int virtio_blk_handle_request(VirtIOBlockReq *req, MultiReqBuffer *mrb)
50
case VIRTIO_BLK_T_IN:
51
{
52
bool is_write = type & VIRTIO_BLK_T_OUT;
53
- req->sector_num = virtio_ldq_p(VIRTIO_DEVICE(req->dev),
54
- &req->out.sector);
55
+ req->sector_num = virtio_ldq_p(vdev, &req->out.sector);
56
57
if (is_write) {
58
qemu_iovec_init_external(&req->qiov, out_iov, out_num);
59
@@ -XXX,XX +XXX,XX @@ static int virtio_blk_handle_request(VirtIOBlockReq *req, MultiReqBuffer *mrb)
60
req->qiov.size / BDRV_SECTOR_SIZE);
61
}
62
63
- if (!virtio_blk_sect_range_ok(req->dev, req->sector_num,
64
- req->qiov.size)) {
65
+ if (!virtio_blk_sect_range_ok(s, req->sector_num, req->qiov.size)) {
66
virtio_blk_req_complete(req, VIRTIO_BLK_S_IOERR);
67
- block_acct_invalid(blk_get_stats(req->dev->blk),
68
+ block_acct_invalid(blk_get_stats(s->blk),
69
is_write ? BLOCK_ACCT_WRITE : BLOCK_ACCT_READ);
70
virtio_blk_free_request(req);
71
return 0;
72
}
73
74
- block_acct_start(blk_get_stats(req->dev->blk),
75
- &req->acct, req->qiov.size,
76
+ block_acct_start(blk_get_stats(s->blk), &req->acct, req->qiov.size,
77
is_write ? BLOCK_ACCT_WRITE : BLOCK_ACCT_READ);
78
79
/* merge would exceed maximum number of requests or IO direction
80
* changes */
81
if (mrb->num_reqs > 0 && (mrb->num_reqs == VIRTIO_BLK_MAX_MERGE_REQS ||
82
is_write != mrb->is_write ||
83
- !req->dev->conf.request_merging)) {
84
- virtio_blk_submit_multireq(req->dev->blk, mrb);
85
+ !s->conf.request_merging)) {
86
+ virtio_blk_submit_multireq(s->blk, mrb);
87
}
88
89
assert(mrb->num_reqs < VIRTIO_BLK_MAX_MERGE_REQS);
90
--
91
2.20.1
92
93
diff view generated by jsdifflib
Deleted patch
1
From: Stefano Garzarella <sgarzare@redhat.com>
2
1
3
We add acct_failed param in order to use virtio_blk_handle_rw_error()
4
also when is not required to call block_acct_failed(). (eg. a discard
5
operation is failed)
6
7
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
8
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
9
Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
10
Acked-by: Pankaj Gupta <pagupta@redhat.com>
11
Message-id: 20190208134950.187665-2-sgarzare@redhat.com
12
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
13
---
14
hw/block/virtio-blk.c | 10 ++++++----
15
1 file changed, 6 insertions(+), 4 deletions(-)
16
17
diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/block/virtio-blk.c
20
+++ b/hw/block/virtio-blk.c
21
@@ -XXX,XX +XXX,XX @@ static void virtio_blk_req_complete(VirtIOBlockReq *req, unsigned char status)
22
}
23
24
static int virtio_blk_handle_rw_error(VirtIOBlockReq *req, int error,
25
- bool is_read)
26
+ bool is_read, bool acct_failed)
27
{
28
VirtIOBlock *s = req->dev;
29
BlockErrorAction action = blk_get_error_action(s->blk, is_read, error);
30
@@ -XXX,XX +XXX,XX @@ static int virtio_blk_handle_rw_error(VirtIOBlockReq *req, int error,
31
s->rq = req;
32
} else if (action == BLOCK_ERROR_ACTION_REPORT) {
33
virtio_blk_req_complete(req, VIRTIO_BLK_S_IOERR);
34
- block_acct_failed(blk_get_stats(s->blk), &req->acct);
35
+ if (acct_failed) {
36
+ block_acct_failed(blk_get_stats(s->blk), &req->acct);
37
+ }
38
virtio_blk_free_request(req);
39
}
40
41
@@ -XXX,XX +XXX,XX @@ static void virtio_blk_rw_complete(void *opaque, int ret)
42
* the memory until the request is completed (which will
43
* happen on the other side of the migration).
44
*/
45
- if (virtio_blk_handle_rw_error(req, -ret, is_read)) {
46
+ if (virtio_blk_handle_rw_error(req, -ret, is_read, true)) {
47
continue;
48
}
49
}
50
@@ -XXX,XX +XXX,XX @@ static void virtio_blk_flush_complete(void *opaque, int ret)
51
52
aio_context_acquire(blk_get_aio_context(s->conf.conf.blk));
53
if (ret) {
54
- if (virtio_blk_handle_rw_error(req, -ret, 0)) {
55
+ if (virtio_blk_handle_rw_error(req, -ret, 0, true)) {
56
goto out;
57
}
58
}
59
--
60
2.20.1
61
62
diff view generated by jsdifflib
Deleted patch
1
From: Stefano Garzarella <sgarzare@redhat.com>
2
1
3
Since configurable features for virtio-blk are growing, this patch
4
adds host_features field in the struct VirtIOBlock. (as in virtio-net)
5
In this way, we can avoid to add new fields for new properties and
6
we can directly set VIRTIO_BLK_F* flags in the host_features.
7
8
We update "config-wce" and "scsi" property definition to use the new
9
host_features field without change the behaviour.
10
11
Suggested-by: Michael S. Tsirkin <mst@redhat.com>
12
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
13
Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
14
Acked-by: Pankaj Gupta <pagupta@redhat.com>
15
Message-id: 20190208134950.187665-3-sgarzare@redhat.com
16
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
17
---
18
include/hw/virtio/virtio-blk.h | 3 +--
19
hw/block/virtio-blk.c | 16 +++++++++-------
20
2 files changed, 10 insertions(+), 9 deletions(-)
21
22
diff --git a/include/hw/virtio/virtio-blk.h b/include/hw/virtio/virtio-blk.h
23
index XXXXXXX..XXXXXXX 100644
24
--- a/include/hw/virtio/virtio-blk.h
25
+++ b/include/hw/virtio/virtio-blk.h
26
@@ -XXX,XX +XXX,XX @@ struct VirtIOBlkConf
27
BlockConf conf;
28
IOThread *iothread;
29
char *serial;
30
- uint32_t scsi;
31
- uint32_t config_wce;
32
uint32_t request_merging;
33
uint16_t num_queues;
34
uint16_t queue_size;
35
@@ -XXX,XX +XXX,XX @@ typedef struct VirtIOBlock {
36
bool dataplane_disabled;
37
bool dataplane_started;
38
struct VirtIOBlockDataPlane *dataplane;
39
+ uint64_t host_features;
40
} VirtIOBlock;
41
42
typedef struct VirtIOBlockReq {
43
diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
44
index XXXXXXX..XXXXXXX 100644
45
--- a/hw/block/virtio-blk.c
46
+++ b/hw/block/virtio-blk.c
47
@@ -XXX,XX +XXX,XX @@ static int virtio_blk_handle_scsi_req(VirtIOBlockReq *req)
48
*/
49
scsi = (void *)elem->in_sg[elem->in_num - 2].iov_base;
50
51
- if (!blk->conf.scsi) {
52
+ if (!virtio_has_feature(blk->host_features, VIRTIO_BLK_F_SCSI)) {
53
status = VIRTIO_BLK_S_UNSUPP;
54
goto fail;
55
}
56
@@ -XXX,XX +XXX,XX @@ static uint64_t virtio_blk_get_features(VirtIODevice *vdev, uint64_t features,
57
{
58
VirtIOBlock *s = VIRTIO_BLK(vdev);
59
60
+ /* Firstly sync all virtio-blk possible supported features */
61
+ features |= s->host_features;
62
+
63
virtio_add_feature(&features, VIRTIO_BLK_F_SEG_MAX);
64
virtio_add_feature(&features, VIRTIO_BLK_F_GEOMETRY);
65
virtio_add_feature(&features, VIRTIO_BLK_F_TOPOLOGY);
66
virtio_add_feature(&features, VIRTIO_BLK_F_BLK_SIZE);
67
if (virtio_has_feature(features, VIRTIO_F_VERSION_1)) {
68
- if (s->conf.scsi) {
69
+ if (virtio_has_feature(s->host_features, VIRTIO_BLK_F_SCSI)) {
70
error_setg(errp, "Please set scsi=off for virtio-blk devices in order to use virtio 1.0");
71
return 0;
72
}
73
@@ -XXX,XX +XXX,XX @@ static uint64_t virtio_blk_get_features(VirtIODevice *vdev, uint64_t features,
74
virtio_add_feature(&features, VIRTIO_BLK_F_SCSI);
75
}
76
77
- if (s->conf.config_wce) {
78
- virtio_add_feature(&features, VIRTIO_BLK_F_CONFIG_WCE);
79
- }
80
if (blk_enable_write_cache(s->blk)) {
81
virtio_add_feature(&features, VIRTIO_BLK_F_WCE);
82
}
83
@@ -XXX,XX +XXX,XX @@ static Property virtio_blk_properties[] = {
84
DEFINE_BLOCK_ERROR_PROPERTIES(VirtIOBlock, conf.conf),
85
DEFINE_BLOCK_CHS_PROPERTIES(VirtIOBlock, conf.conf),
86
DEFINE_PROP_STRING("serial", VirtIOBlock, conf.serial),
87
- DEFINE_PROP_BIT("config-wce", VirtIOBlock, conf.config_wce, 0, true),
88
+ DEFINE_PROP_BIT64("config-wce", VirtIOBlock, host_features,
89
+ VIRTIO_BLK_F_CONFIG_WCE, true),
90
#ifdef __linux__
91
- DEFINE_PROP_BIT("scsi", VirtIOBlock, conf.scsi, 0, false),
92
+ DEFINE_PROP_BIT64("scsi", VirtIOBlock, host_features,
93
+ VIRTIO_BLK_F_SCSI, false),
94
#endif
95
DEFINE_PROP_BIT("request-merging", VirtIOBlock, conf.request_merging, 0,
96
true),
97
--
98
2.20.1
99
100
diff view generated by jsdifflib
1
From: Stefano Garzarella <sgarzare@redhat.com>
1
From: Eric Blake <eblake@redhat.com>
2
2
3
If the WRITE_ZEROES feature is enabled, we check this command
3
Use consistent capitalization, and fix a missed line (we duplicate the
4
in the test_basic().
4
qemu-img synopses in too many places).
5
5
6
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
6
Fixes: 1899bf4737 (qemu-img: Add -F shorthand to convert)
7
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
7
Signed-off-by: Eric Blake <eblake@redhat.com>
8
Acked-by: Thomas Huth <thuth@redhat.com>
8
Message-Id: <20210921142812.2631605-1-eblake@redhat.com>
9
Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
9
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
10
Acked-by: Pankaj Gupta <pagupta@redhat.com>
10
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
11
Message-id: 20190208134950.187665-7-sgarzare@redhat.com
12
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
13
---
11
---
14
tests/virtio-blk-test.c | 60 +++++++++++++++++++++++++++++++++++++++++
12
docs/tools/qemu-img.rst | 2 +-
15
1 file changed, 60 insertions(+)
13
qemu-img-cmds.hx | 2 +-
14
2 files changed, 2 insertions(+), 2 deletions(-)
16
15
17
diff --git a/tests/virtio-blk-test.c b/tests/virtio-blk-test.c
16
diff --git a/docs/tools/qemu-img.rst b/docs/tools/qemu-img.rst
18
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
19
--- a/tests/virtio-blk-test.c
18
--- a/docs/tools/qemu-img.rst
20
+++ b/tests/virtio-blk-test.c
19
+++ b/docs/tools/qemu-img.rst
21
@@ -XXX,XX +XXX,XX @@ static void test_basic(QVirtioDevice *dev, QGuestAllocator *alloc,
20
@@ -XXX,XX +XXX,XX @@ Command description:
22
21
4
23
guest_free(alloc, req_addr);
22
Error on reading data
24
23
25
+ if (features & (1u << VIRTIO_BLK_F_WRITE_ZEROES)) {
24
-.. option:: convert [--object OBJECTDEF] [--image-opts] [--target-image-opts] [--target-is-zero] [--bitmaps [--skip-broken-bitmaps]] [-U] [-C] [-c] [-p] [-q] [-n] [-f FMT] [-t CACHE] [-T SRC_CACHE] [-O OUTPUT_FMT] [-B BACKING_FILE [-F backing_fmt]] [-o OPTIONS] [-l SNAPSHOT_PARAM] [-S SPARSE_SIZE] [-r RATE_LIMIT] [-m NUM_COROUTINES] [-W] FILENAME [FILENAME2 [...]] OUTPUT_FILENAME
26
+ struct virtio_blk_discard_write_zeroes dwz_hdr;
25
+.. option:: convert [--object OBJECTDEF] [--image-opts] [--target-image-opts] [--target-is-zero] [--bitmaps [--skip-broken-bitmaps]] [-U] [-C] [-c] [-p] [-q] [-n] [-f FMT] [-t CACHE] [-T SRC_CACHE] [-O OUTPUT_FMT] [-B BACKING_FILE [-F BACKING_FMT]] [-o OPTIONS] [-l SNAPSHOT_PARAM] [-S SPARSE_SIZE] [-r RATE_LIMIT] [-m NUM_COROUTINES] [-W] FILENAME [FILENAME2 [...]] OUTPUT_FILENAME
27
+ void *expected;
26
28
+
27
Convert the disk image *FILENAME* or a snapshot *SNAPSHOT_PARAM*
29
+ /*
28
to disk image *OUTPUT_FILENAME* using format *OUTPUT_FMT*. It can
30
+ * WRITE_ZEROES request on the same sector of previous test where
29
diff --git a/qemu-img-cmds.hx b/qemu-img-cmds.hx
31
+ * we wrote "TEST".
30
index XXXXXXX..XXXXXXX 100644
32
+ */
31
--- a/qemu-img-cmds.hx
33
+ req.type = VIRTIO_BLK_T_WRITE_ZEROES;
32
+++ b/qemu-img-cmds.hx
34
+ req.data = (char *) &dwz_hdr;
33
@@ -XXX,XX +XXX,XX @@ ERST
35
+ dwz_hdr.sector = 0;
34
DEF("convert", img_convert,
36
+ dwz_hdr.num_sectors = 1;
35
"convert [--object objectdef] [--image-opts] [--target-image-opts] [--target-is-zero] [--bitmaps] [-U] [-C] [-c] [-p] [-q] [-n] [-f fmt] [-t cache] [-T src_cache] [-O output_fmt] [-B backing_file [-F backing_fmt]] [-o options] [-l snapshot_param] [-S sparse_size] [-r rate_limit] [-m num_coroutines] [-W] [--salvage] filename [filename2 [...]] output_filename")
37
+ dwz_hdr.flags = 0;
36
SRST
38
+
37
-.. option:: convert [--object OBJECTDEF] [--image-opts] [--target-image-opts] [--target-is-zero] [--bitmaps] [-U] [-C] [-c] [-p] [-q] [-n] [-f FMT] [-t CACHE] [-T SRC_CACHE] [-O OUTPUT_FMT] [-B BACKING_FILE] [-o OPTIONS] [-l SNAPSHOT_PARAM] [-S SPARSE_SIZE] [-r RATE_LIMIT] [-m NUM_COROUTINES] [-W] [--salvage] FILENAME [FILENAME2 [...]] OUTPUT_FILENAME
39
+ req_addr = virtio_blk_request(alloc, dev, &req, sizeof(dwz_hdr));
38
+.. option:: convert [--object OBJECTDEF] [--image-opts] [--target-image-opts] [--target-is-zero] [--bitmaps] [-U] [-C] [-c] [-p] [-q] [-n] [-f FMT] [-t CACHE] [-T SRC_CACHE] [-O OUTPUT_FMT] [-B BACKING_FILE [-F BACKING_FMT]] [-o OPTIONS] [-l SNAPSHOT_PARAM] [-S SPARSE_SIZE] [-r RATE_LIMIT] [-m NUM_COROUTINES] [-W] [--salvage] FILENAME [FILENAME2 [...]] OUTPUT_FILENAME
40
+
39
ERST
41
+ free_head = qvirtqueue_add(vq, req_addr, 16, false, true);
40
42
+ qvirtqueue_add(vq, req_addr + 16, sizeof(dwz_hdr), false, true);
41
DEF("create", img_create,
43
+ qvirtqueue_add(vq, req_addr + 16 + sizeof(dwz_hdr), 1, true, false);
44
+
45
+ qvirtqueue_kick(dev, vq, free_head);
46
+
47
+ qvirtio_wait_used_elem(dev, vq, free_head, NULL,
48
+ QVIRTIO_BLK_TIMEOUT_US);
49
+ status = readb(req_addr + 16 + sizeof(dwz_hdr));
50
+ g_assert_cmpint(status, ==, 0);
51
+
52
+ guest_free(alloc, req_addr);
53
+
54
+ /* Read request to check if the sector contains all zeroes */
55
+ req.type = VIRTIO_BLK_T_IN;
56
+ req.ioprio = 1;
57
+ req.sector = 0;
58
+ req.data = g_malloc0(512);
59
+
60
+ req_addr = virtio_blk_request(alloc, dev, &req, 512);
61
+
62
+ g_free(req.data);
63
+
64
+ free_head = qvirtqueue_add(vq, req_addr, 16, false, true);
65
+ qvirtqueue_add(vq, req_addr + 16, 512, true, true);
66
+ qvirtqueue_add(vq, req_addr + 528, 1, true, false);
67
+
68
+ qvirtqueue_kick(dev, vq, free_head);
69
+
70
+ qvirtio_wait_used_elem(dev, vq, free_head, NULL,
71
+ QVIRTIO_BLK_TIMEOUT_US);
72
+ status = readb(req_addr + 528);
73
+ g_assert_cmpint(status, ==, 0);
74
+
75
+ data = g_malloc(512);
76
+ expected = g_malloc0(512);
77
+ memread(req_addr + 16, data, 512);
78
+ g_assert_cmpmem(data, 512, expected, 512);
79
+ g_free(expected);
80
+ g_free(data);
81
+
82
+ guest_free(alloc, req_addr);
83
+ }
84
+
85
if (features & (1u << VIRTIO_F_ANY_LAYOUT)) {
86
/* Write and read with 2 descriptor layout */
87
/* Write request */
88
--
42
--
89
2.20.1
43
2.31.1
90
44
91
45
diff view generated by jsdifflib
1
From: Stefano Garzarella <sgarzare@redhat.com>
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
2
3
This patch adds the support of DISCARD and WRITE_ZEROES commands,
3
Test 297 in tests/qemu-iotests currently fails: pylint has
4
that have been introduced in the virtio-blk protocol to have
4
learned new things to check, or we simply missed them.
5
better performance when using SSD backend.
6
5
7
We support only one segment per request since multiple segments
6
All fixes in this patch are related to additional spaces used
8
are not widely used and there are no userspace APIs that allow
7
or wrong indentation. No functional change intended.
9
applications to submit multiple segments in a single call.
10
8
11
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
9
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
12
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
10
Message-Id: <20211008062821.1010967-2-eesposit@redhat.com>
13
Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
11
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
14
Acked-by: Pankaj Gupta <pagupta@redhat.com>
15
Message-id: 20190208134950.187665-5-sgarzare@redhat.com
16
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
17
---
12
---
18
include/hw/virtio/virtio-blk.h | 2 +
13
tests/qemu-iotests/129 | 18 +++++++++---------
19
hw/block/virtio-blk.c | 184 +++++++++++++++++++++++++++++++++
14
tests/qemu-iotests/310 | 16 ++++++++--------
20
2 files changed, 186 insertions(+)
15
tests/qemu-iotests/check | 11 ++++++-----
16
tests/qemu-iotests/iotests.py | 7 ++++---
17
tests/qemu-iotests/tests/image-fleecing | 4 ++--
18
5 files changed, 29 insertions(+), 27 deletions(-)
21
19
22
diff --git a/include/hw/virtio/virtio-blk.h b/include/hw/virtio/virtio-blk.h
20
diff --git a/tests/qemu-iotests/129 b/tests/qemu-iotests/129
21
index XXXXXXX..XXXXXXX 100755
22
--- a/tests/qemu-iotests/129
23
+++ b/tests/qemu-iotests/129
24
@@ -XXX,XX +XXX,XX @@ class TestStopWithBlockJob(iotests.QMPTestCase):
25
self.do_test_stop("drive-backup", device="drive0",
26
target=self.target_img, format=iotests.imgfmt,
27
sync="full",
28
- x_perf={ 'max-chunk': 65536,
29
- 'max-workers': 8 })
30
+ x_perf={'max-chunk': 65536,
31
+ 'max-workers': 8})
32
33
def test_block_commit(self):
34
# Add overlay above the source node so that we actually use a
35
@@ -XXX,XX +XXX,XX @@ class TestStopWithBlockJob(iotests.QMPTestCase):
36
'1G')
37
38
result = self.vm.qmp('blockdev-add', **{
39
- 'node-name': 'overlay',
40
- 'driver': iotests.imgfmt,
41
- 'file': {
42
- 'driver': 'file',
43
- 'filename': self.overlay_img
44
- }
45
- })
46
+ 'node-name': 'overlay',
47
+ 'driver': iotests.imgfmt,
48
+ 'file': {
49
+ 'driver': 'file',
50
+ 'filename': self.overlay_img
51
+ }
52
+ })
53
self.assert_qmp(result, 'return', {})
54
55
result = self.vm.qmp('blockdev-snapshot',
56
diff --git a/tests/qemu-iotests/310 b/tests/qemu-iotests/310
57
index XXXXXXX..XXXXXXX 100755
58
--- a/tests/qemu-iotests/310
59
+++ b/tests/qemu-iotests/310
60
@@ -XXX,XX +XXX,XX @@ with iotests.FilePath('base.img') as base_img_path, \
61
assert qemu_io_silent(base_img_path, '-c', 'write -P 1 3M 1M') == 0
62
assert qemu_img('create', '-f', iotests.imgfmt, '-b', base_img_path,
63
'-F', iotests.imgfmt, mid_img_path) == 0
64
- assert qemu_io_silent(mid_img_path, '-c', 'write -P 3 2M 1M') == 0
65
- assert qemu_io_silent(mid_img_path, '-c', 'write -P 3 4M 1M') == 0
66
+ assert qemu_io_silent(mid_img_path, '-c', 'write -P 3 2M 1M') == 0
67
+ assert qemu_io_silent(mid_img_path, '-c', 'write -P 3 4M 1M') == 0
68
assert qemu_img('create', '-f', iotests.imgfmt, '-b', mid_img_path,
69
'-F', iotests.imgfmt, top_img_path) == 0
70
- assert qemu_io_silent(top_img_path, '-c', 'write -P 2 1M 1M') == 0
71
+ assert qemu_io_silent(top_img_path, '-c', 'write -P 2 1M 1M') == 0
72
73
# 0 1 2 3 4
74
# top 2
75
@@ -XXX,XX +XXX,XX @@ with iotests.FilePath('base.img') as base_img_path, \
76
assert qemu_img('rebase', '-u', '-b', '', '-f', iotests.imgfmt,
77
top_img_path) == 0
78
79
- assert qemu_io_silent(top_img_path, '-c', 'read -P 0 0 1M') == 0
80
- assert qemu_io_silent(top_img_path, '-c', 'read -P 2 1M 1M') == 0
81
- assert qemu_io_silent(top_img_path, '-c', 'read -P 3 2M 1M') == 0
82
- assert qemu_io_silent(top_img_path, '-c', 'read -P 0 3M 1M') == 0
83
- assert qemu_io_silent(top_img_path, '-c', 'read -P 3 4M 1M') == 0
84
+ assert qemu_io_silent(top_img_path, '-c', 'read -P 0 0 1M') == 0
85
+ assert qemu_io_silent(top_img_path, '-c', 'read -P 2 1M 1M') == 0
86
+ assert qemu_io_silent(top_img_path, '-c', 'read -P 3 2M 1M') == 0
87
+ assert qemu_io_silent(top_img_path, '-c', 'read -P 0 3M 1M') == 0
88
+ assert qemu_io_silent(top_img_path, '-c', 'read -P 3 4M 1M') == 0
89
90
log('Done')
91
diff --git a/tests/qemu-iotests/check b/tests/qemu-iotests/check
92
index XXXXXXX..XXXXXXX 100755
93
--- a/tests/qemu-iotests/check
94
+++ b/tests/qemu-iotests/check
95
@@ -XXX,XX +XXX,XX @@ def make_argparser() -> argparse.ArgumentParser:
96
97
p.add_argument('-d', dest='debug', action='store_true', help='debug')
98
p.add_argument('-p', dest='print', action='store_true',
99
- help='redirects qemu\'s stdout and stderr to the test output')
100
+ help='redirects qemu\'s stdout and stderr to '
101
+ 'the test output')
102
p.add_argument('-gdb', action='store_true',
103
- help="start gdbserver with $GDB_OPTIONS options \
104
- ('localhost:12345' if $GDB_OPTIONS is empty)")
105
+ help="start gdbserver with $GDB_OPTIONS options "
106
+ "('localhost:12345' if $GDB_OPTIONS is empty)")
107
p.add_argument('-valgrind', action='store_true',
108
- help='use valgrind, sets VALGRIND_QEMU environment '
109
- 'variable')
110
+ help='use valgrind, sets VALGRIND_QEMU environment '
111
+ 'variable')
112
113
p.add_argument('-misalign', action='store_true',
114
help='misalign memory allocations')
115
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
23
index XXXXXXX..XXXXXXX 100644
116
index XXXXXXX..XXXXXXX 100644
24
--- a/include/hw/virtio/virtio-blk.h
117
--- a/tests/qemu-iotests/iotests.py
25
+++ b/include/hw/virtio/virtio-blk.h
118
+++ b/tests/qemu-iotests/iotests.py
26
@@ -XXX,XX +XXX,XX @@ struct VirtIOBlkConf
119
@@ -XXX,XX +XXX,XX @@ def _post_shutdown(self) -> None:
27
uint32_t request_merging;
120
super()._post_shutdown()
28
uint16_t num_queues;
121
if not qemu_valgrind or not self._popen:
29
uint16_t queue_size;
122
return
30
+ uint32_t max_discard_sectors;
123
- valgrind_filename = f"{test_dir}/{self._popen.pid}.valgrind"
31
+ uint32_t max_write_zeroes_sectors;
124
+ valgrind_filename = f"{test_dir}/{self._popen.pid}.valgrind"
32
};
125
if self.exitcode() == 99:
33
126
with open(valgrind_filename, encoding='utf-8') as f:
34
struct VirtIOBlockDataPlane;
127
print(f.read())
35
diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
128
@@ -XXX,XX +XXX,XX @@ def write(self, arg=None):
36
index XXXXXXX..XXXXXXX 100644
129
37
--- a/hw/block/virtio-blk.c
130
class ReproducibleTestRunner(unittest.TextTestRunner):
38
+++ b/hw/block/virtio-blk.c
131
def __init__(self, stream: Optional[TextIO] = None,
39
@@ -XXX,XX +XXX,XX @@ out:
132
- resultclass: Type[unittest.TestResult] = ReproducibleTestResult,
40
aio_context_release(blk_get_aio_context(s->conf.conf.blk));
133
- **kwargs: Any) -> None:
41
}
134
+ resultclass: Type[unittest.TestResult] =
42
135
+ ReproducibleTestResult,
43
+static void virtio_blk_discard_write_zeroes_complete(void *opaque, int ret)
136
+ **kwargs: Any) -> None:
44
+{
137
rstream = ReproducibleStreamWrapper(stream or sys.stdout)
45
+ VirtIOBlockReq *req = opaque;
138
super().__init__(stream=rstream, # type: ignore
46
+ VirtIOBlock *s = req->dev;
139
descriptions=True,
47
+ bool is_write_zeroes = (virtio_ldl_p(VIRTIO_DEVICE(s), &req->out.type) &
140
diff --git a/tests/qemu-iotests/tests/image-fleecing b/tests/qemu-iotests/tests/image-fleecing
48
+ ~VIRTIO_BLK_T_BARRIER) == VIRTIO_BLK_T_WRITE_ZEROES;
141
index XXXXXXX..XXXXXXX 100755
49
+
142
--- a/tests/qemu-iotests/tests/image-fleecing
50
+ aio_context_acquire(blk_get_aio_context(s->conf.conf.blk));
143
+++ b/tests/qemu-iotests/tests/image-fleecing
51
+ if (ret) {
144
@@ -XXX,XX +XXX,XX @@ def do_test(use_cbw, base_img_path, fleece_img_path, nbd_sock_path, vm):
52
+ if (virtio_blk_handle_rw_error(req, -ret, false, is_write_zeroes)) {
145
53
+ goto out;
146
nbd_uri = 'nbd+unix:///%s?socket=%s' % (tmp_node, nbd_sock_path)
54
+ }
147
log(vm.qmp('nbd-server-start',
55
+ }
148
- {'addr': { 'type': 'unix',
56
+
149
- 'data': { 'path': nbd_sock_path } } }))
57
+ virtio_blk_req_complete(req, VIRTIO_BLK_S_OK);
150
+ {'addr': {'type': 'unix',
58
+ if (is_write_zeroes) {
151
+ 'data': {'path': nbd_sock_path}}}))
59
+ block_acct_done(blk_get_stats(s->blk), &req->acct);
152
60
+ }
153
log(vm.qmp('nbd-server-add', device=tmp_node))
61
+ virtio_blk_free_request(req);
62
+
63
+out:
64
+ aio_context_release(blk_get_aio_context(s->conf.conf.blk));
65
+}
66
+
67
#ifdef __linux__
68
69
typedef struct {
70
@@ -XXX,XX +XXX,XX @@ static bool virtio_blk_sect_range_ok(VirtIOBlock *dev,
71
return true;
72
}
73
74
+static uint8_t virtio_blk_handle_discard_write_zeroes(VirtIOBlockReq *req,
75
+ struct virtio_blk_discard_write_zeroes *dwz_hdr, bool is_write_zeroes)
76
+{
77
+ VirtIOBlock *s = req->dev;
78
+ VirtIODevice *vdev = VIRTIO_DEVICE(s);
79
+ uint64_t sector;
80
+ uint32_t num_sectors, flags, max_sectors;
81
+ uint8_t err_status;
82
+ int bytes;
83
+
84
+ sector = virtio_ldq_p(vdev, &dwz_hdr->sector);
85
+ num_sectors = virtio_ldl_p(vdev, &dwz_hdr->num_sectors);
86
+ flags = virtio_ldl_p(vdev, &dwz_hdr->flags);
87
+ max_sectors = is_write_zeroes ? s->conf.max_write_zeroes_sectors :
88
+ s->conf.max_discard_sectors;
89
+
90
+ /*
91
+ * max_sectors is at most BDRV_REQUEST_MAX_SECTORS, this check
92
+ * make us sure that "num_sectors << BDRV_SECTOR_BITS" can fit in
93
+ * the integer variable.
94
+ */
95
+ if (unlikely(num_sectors > max_sectors)) {
96
+ err_status = VIRTIO_BLK_S_IOERR;
97
+ goto err;
98
+ }
99
+
100
+ bytes = num_sectors << BDRV_SECTOR_BITS;
101
+
102
+ if (unlikely(!virtio_blk_sect_range_ok(s, sector, bytes))) {
103
+ err_status = VIRTIO_BLK_S_IOERR;
104
+ goto err;
105
+ }
106
+
107
+ /*
108
+ * The device MUST set the status byte to VIRTIO_BLK_S_UNSUPP for discard
109
+ * and write zeroes commands if any unknown flag is set.
110
+ */
111
+ if (unlikely(flags & ~VIRTIO_BLK_WRITE_ZEROES_FLAG_UNMAP)) {
112
+ err_status = VIRTIO_BLK_S_UNSUPP;
113
+ goto err;
114
+ }
115
+
116
+ if (is_write_zeroes) { /* VIRTIO_BLK_T_WRITE_ZEROES */
117
+ int blk_aio_flags = 0;
118
+
119
+ if (flags & VIRTIO_BLK_WRITE_ZEROES_FLAG_UNMAP) {
120
+ blk_aio_flags |= BDRV_REQ_MAY_UNMAP;
121
+ }
122
+
123
+ block_acct_start(blk_get_stats(s->blk), &req->acct, bytes,
124
+ BLOCK_ACCT_WRITE);
125
+
126
+ blk_aio_pwrite_zeroes(s->blk, sector << BDRV_SECTOR_BITS,
127
+ bytes, blk_aio_flags,
128
+ virtio_blk_discard_write_zeroes_complete, req);
129
+ } else { /* VIRTIO_BLK_T_DISCARD */
130
+ /*
131
+ * The device MUST set the status byte to VIRTIO_BLK_S_UNSUPP for
132
+ * discard commands if the unmap flag is set.
133
+ */
134
+ if (unlikely(flags & VIRTIO_BLK_WRITE_ZEROES_FLAG_UNMAP)) {
135
+ err_status = VIRTIO_BLK_S_UNSUPP;
136
+ goto err;
137
+ }
138
+
139
+ blk_aio_pdiscard(s->blk, sector << BDRV_SECTOR_BITS, bytes,
140
+ virtio_blk_discard_write_zeroes_complete, req);
141
+ }
142
+
143
+ return VIRTIO_BLK_S_OK;
144
+
145
+err:
146
+ if (is_write_zeroes) {
147
+ block_acct_invalid(blk_get_stats(s->blk), BLOCK_ACCT_WRITE);
148
+ }
149
+ return err_status;
150
+}
151
+
152
static int virtio_blk_handle_request(VirtIOBlockReq *req, MultiReqBuffer *mrb)
153
{
154
uint32_t type;
155
@@ -XXX,XX +XXX,XX @@ static int virtio_blk_handle_request(VirtIOBlockReq *req, MultiReqBuffer *mrb)
156
virtio_blk_free_request(req);
157
break;
158
}
159
+ /*
160
+ * VIRTIO_BLK_T_DISCARD and VIRTIO_BLK_T_WRITE_ZEROES are defined with
161
+ * VIRTIO_BLK_T_OUT flag set. We masked this flag in the switch statement,
162
+ * so we must mask it for these requests, then we will check if it is set.
163
+ */
164
+ case VIRTIO_BLK_T_DISCARD & ~VIRTIO_BLK_T_OUT:
165
+ case VIRTIO_BLK_T_WRITE_ZEROES & ~VIRTIO_BLK_T_OUT:
166
+ {
167
+ struct virtio_blk_discard_write_zeroes dwz_hdr;
168
+ size_t out_len = iov_size(out_iov, out_num);
169
+ bool is_write_zeroes = (type & ~VIRTIO_BLK_T_BARRIER) ==
170
+ VIRTIO_BLK_T_WRITE_ZEROES;
171
+ uint8_t err_status;
172
+
173
+ /*
174
+ * Unsupported if VIRTIO_BLK_T_OUT is not set or the request contains
175
+ * more than one segment.
176
+ */
177
+ if (unlikely(!(type & VIRTIO_BLK_T_OUT) ||
178
+ out_len > sizeof(dwz_hdr))) {
179
+ virtio_blk_req_complete(req, VIRTIO_BLK_S_UNSUPP);
180
+ virtio_blk_free_request(req);
181
+ return 0;
182
+ }
183
+
184
+ if (unlikely(iov_to_buf(out_iov, out_num, 0, &dwz_hdr,
185
+ sizeof(dwz_hdr)) != sizeof(dwz_hdr))) {
186
+ virtio_error(vdev, "virtio-blk discard/write_zeroes header"
187
+ " too short");
188
+ return -1;
189
+ }
190
+
191
+ err_status = virtio_blk_handle_discard_write_zeroes(req, &dwz_hdr,
192
+ is_write_zeroes);
193
+ if (err_status != VIRTIO_BLK_S_OK) {
194
+ virtio_blk_req_complete(req, err_status);
195
+ virtio_blk_free_request(req);
196
+ }
197
+
198
+ break;
199
+ }
200
default:
201
virtio_blk_req_complete(req, VIRTIO_BLK_S_UNSUPP);
202
virtio_blk_free_request(req);
203
@@ -XXX,XX +XXX,XX @@ static void virtio_blk_update_config(VirtIODevice *vdev, uint8_t *config)
204
blkcfg.alignment_offset = 0;
205
blkcfg.wce = blk_enable_write_cache(s->blk);
206
virtio_stw_p(vdev, &blkcfg.num_queues, s->conf.num_queues);
207
+ if (virtio_has_feature(s->host_features, VIRTIO_BLK_F_DISCARD)) {
208
+ virtio_stl_p(vdev, &blkcfg.max_discard_sectors,
209
+ s->conf.max_discard_sectors);
210
+ virtio_stl_p(vdev, &blkcfg.discard_sector_alignment,
211
+ blk_size >> BDRV_SECTOR_BITS);
212
+ /*
213
+ * We support only one segment per request since multiple segments
214
+ * are not widely used and there are no userspace APIs that allow
215
+ * applications to submit multiple segments in a single call.
216
+ */
217
+ virtio_stl_p(vdev, &blkcfg.max_discard_seg, 1);
218
+ }
219
+ if (virtio_has_feature(s->host_features, VIRTIO_BLK_F_WRITE_ZEROES)) {
220
+ virtio_stl_p(vdev, &blkcfg.max_write_zeroes_sectors,
221
+ s->conf.max_write_zeroes_sectors);
222
+ blkcfg.write_zeroes_may_unmap = 1;
223
+ virtio_stl_p(vdev, &blkcfg.max_write_zeroes_seg, 1);
224
+ }
225
memcpy(config, &blkcfg, sizeof(struct virtio_blk_config));
226
}
227
228
@@ -XXX,XX +XXX,XX @@ static void virtio_blk_device_realize(DeviceState *dev, Error **errp)
229
return;
230
}
231
232
+ if (virtio_has_feature(s->host_features, VIRTIO_BLK_F_DISCARD) &&
233
+ (!conf->max_discard_sectors ||
234
+ conf->max_discard_sectors > BDRV_REQUEST_MAX_SECTORS)) {
235
+ error_setg(errp, "invalid max-discard-sectors property (%" PRIu32 ")"
236
+ ", must be between 1 and %d",
237
+ conf->max_discard_sectors, (int)BDRV_REQUEST_MAX_SECTORS);
238
+ return;
239
+ }
240
+
241
+ if (virtio_has_feature(s->host_features, VIRTIO_BLK_F_WRITE_ZEROES) &&
242
+ (!conf->max_write_zeroes_sectors ||
243
+ conf->max_write_zeroes_sectors > BDRV_REQUEST_MAX_SECTORS)) {
244
+ error_setg(errp, "invalid max-write-zeroes-sectors property (%" PRIu32
245
+ "), must be between 1 and %d",
246
+ conf->max_write_zeroes_sectors,
247
+ (int)BDRV_REQUEST_MAX_SECTORS);
248
+ return;
249
+ }
250
+
251
virtio_init(vdev, "virtio-blk", VIRTIO_ID_BLOCK,
252
sizeof(struct virtio_blk_config));
253
254
@@ -XXX,XX +XXX,XX @@ static Property virtio_blk_properties[] = {
255
VIRTIO_BLK_F_DISCARD, true),
256
DEFINE_PROP_BIT64("write-zeroes", VirtIOBlock, host_features,
257
VIRTIO_BLK_F_WRITE_ZEROES, true),
258
+ DEFINE_PROP_UINT32("max-discard-sectors", VirtIOBlock,
259
+ conf.max_discard_sectors, BDRV_REQUEST_MAX_SECTORS),
260
+ DEFINE_PROP_UINT32("max-write-zeroes-sectors", VirtIOBlock,
261
+ conf.max_write_zeroes_sectors, BDRV_REQUEST_MAX_SECTORS),
262
DEFINE_PROP_END_OF_LIST(),
263
};
264
154
265
--
155
--
266
2.20.1
156
2.31.1
267
157
268
158
diff view generated by jsdifflib
1
From: Stefano Garzarella <sgarzare@redhat.com>
1
From: Thomas Weißschuh <thomas.weissschuh.ext@zeiss.com>
2
2
3
The size of data in the virtio_blk_request must be a multiple
3
VMDK files support an attribute that represents the version of the guest
4
of 512 bytes for IN and OUT requests, or a multiple of the size
4
tools that are installed on the disk.
5
of struct virtio_blk_discard_write_zeroes for DISCARD and
5
This attribute is used by vSphere before a machine has been started to
6
WRITE_ZEROES requests.
6
determine if the VM has the guest tools installed.
7
This is important when configuring "Operating system customizations" in
8
vSphere, as it checks for the presence of the guest tools before
9
allowing those customizations.
10
Thus when the VM has not yet booted normally it would be impossible to
11
customize it, therefore preventing a customized first-boot.
7
12
8
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
13
The attribute should not hurt on disks that do not have the guest tools
9
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
14
installed and indeed the VMware tools also unconditionally add this
10
Reviewed-by: Thomas Huth <thuth@redhat.com>
15
attribute.
11
Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
16
(Defaulting to the value "2147483647", as is done in this patch)
12
Acked-by: Pankaj Gupta <pagupta@redhat.com>
17
13
Message-id: 20190208134950.187665-6-sgarzare@redhat.com
18
Signed-off-by: Thomas Weißschuh <thomas.weissschuh.ext@zeiss.com>
14
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
19
Message-Id: <20210913130419.13241-1-thomas.weissschuh.ext@zeiss.com>
20
[hreitz: Added missing '#' in block-core.json]
21
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
15
---
22
---
16
tests/virtio-blk-test.c | 15 ++++++++++++++-
23
qapi/block-core.json | 3 +++
17
1 file changed, 14 insertions(+), 1 deletion(-)
24
block/vmdk.c | 24 ++++++++++++++++++++----
25
2 files changed, 23 insertions(+), 4 deletions(-)
18
26
19
diff --git a/tests/virtio-blk-test.c b/tests/virtio-blk-test.c
27
diff --git a/qapi/block-core.json b/qapi/block-core.json
20
index XXXXXXX..XXXXXXX 100644
28
index XXXXXXX..XXXXXXX 100644
21
--- a/tests/virtio-blk-test.c
29
--- a/qapi/block-core.json
22
+++ b/tests/virtio-blk-test.c
30
+++ b/qapi/block-core.json
23
@@ -XXX,XX +XXX,XX @@ static uint64_t virtio_blk_request(QGuestAllocator *alloc, QVirtioDevice *d,
31
@@ -XXX,XX +XXX,XX @@
24
uint64_t addr;
32
# @adapter-type: The adapter type used to fill in the descriptor. Default: ide.
25
uint8_t status = 0xFF;
33
# @hwversion: Hardware version. The meaningful options are "4" or "6".
26
34
# Default: "4".
27
- g_assert_cmpuint(data_size % 512, ==, 0);
35
+# @toolsversion: VMware guest tools version.
28
+ switch (req->type) {
36
+# Default: "2147483647" (Since 6.2)
29
+ case VIRTIO_BLK_T_IN:
37
# @zeroed-grain: Whether to enable zeroed-grain feature for sparse subformats.
30
+ case VIRTIO_BLK_T_OUT:
38
# Default: false.
31
+ g_assert_cmpuint(data_size % 512, ==, 0);
39
#
32
+ break;
40
@@ -XXX,XX +XXX,XX @@
33
+ case VIRTIO_BLK_T_DISCARD:
41
'*backing-file': 'str',
34
+ case VIRTIO_BLK_T_WRITE_ZEROES:
42
'*adapter-type': 'BlockdevVmdkAdapterType',
35
+ g_assert_cmpuint(data_size %
43
'*hwversion': 'str',
36
+ sizeof(struct virtio_blk_discard_write_zeroes), ==, 0);
44
+ '*toolsversion': 'str',
37
+ break;
45
'*zeroed-grain': 'bool' } }
38
+ default:
46
39
+ g_assert_cmpuint(data_size, ==, 0);
47
48
diff --git a/block/vmdk.c b/block/vmdk.c
49
index XXXXXXX..XXXXXXX 100644
50
--- a/block/vmdk.c
51
+++ b/block/vmdk.c
52
@@ -XXX,XX +XXX,XX @@
53
#define VMDK_ZEROED (-3)
54
55
#define BLOCK_OPT_ZEROED_GRAIN "zeroed_grain"
56
+#define BLOCK_OPT_TOOLSVERSION "toolsversion"
57
58
typedef struct {
59
uint32_t version;
60
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vmdk_co_do_create(int64_t size,
61
BlockdevVmdkAdapterType adapter_type,
62
const char *backing_file,
63
const char *hw_version,
64
+ const char *toolsversion,
65
bool compat6,
66
bool zeroed_grain,
67
vmdk_create_extent_fn extent_fn,
68
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vmdk_co_do_create(int64_t size,
69
"ddb.geometry.cylinders = \"%" PRId64 "\"\n"
70
"ddb.geometry.heads = \"%" PRIu32 "\"\n"
71
"ddb.geometry.sectors = \"63\"\n"
72
- "ddb.adapterType = \"%s\"\n";
73
+ "ddb.adapterType = \"%s\"\n"
74
+ "ddb.toolsVersion = \"%s\"\n";
75
76
ext_desc_lines = g_string_new(NULL);
77
78
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vmdk_co_do_create(int64_t size,
79
if (!hw_version) {
80
hw_version = "4";
81
}
82
+ if (!toolsversion) {
83
+ toolsversion = "2147483647";
40
+ }
84
+ }
41
+
85
42
addr = guest_alloc(alloc, sizeof(*req) + data_size);
86
if (adapter_type != BLOCKDEV_VMDK_ADAPTER_TYPE_IDE) {
43
87
/* that's the number of heads with which vmware operates when
44
virtio_blk_fix_request(d, req);
88
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vmdk_co_do_create(int64_t size,
89
size /
90
(int64_t)(63 * number_heads * BDRV_SECTOR_SIZE),
91
number_heads,
92
- BlockdevVmdkAdapterType_str(adapter_type));
93
+ BlockdevVmdkAdapterType_str(adapter_type),
94
+ toolsversion);
95
desc_len = strlen(desc);
96
/* the descriptor offset = 0x200 */
97
if (!split && !flat) {
98
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vmdk_co_create_opts(BlockDriver *drv,
99
BlockdevVmdkAdapterType adapter_type_enum;
100
char *backing_file = NULL;
101
char *hw_version = NULL;
102
+ char *toolsversion = NULL;
103
char *fmt = NULL;
104
BlockdevVmdkSubformat subformat;
105
int ret = 0;
106
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vmdk_co_create_opts(BlockDriver *drv,
107
adapter_type = qemu_opt_get_del(opts, BLOCK_OPT_ADAPTER_TYPE);
108
backing_file = qemu_opt_get_del(opts, BLOCK_OPT_BACKING_FILE);
109
hw_version = qemu_opt_get_del(opts, BLOCK_OPT_HWVERSION);
110
+ toolsversion = qemu_opt_get_del(opts, BLOCK_OPT_TOOLSVERSION);
111
compat6 = qemu_opt_get_bool_del(opts, BLOCK_OPT_COMPAT6, false);
112
if (strcmp(hw_version, "undefined") == 0) {
113
g_free(hw_version);
114
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vmdk_co_create_opts(BlockDriver *drv,
115
.opts = opts,
116
};
117
ret = vmdk_co_do_create(total_size, subformat, adapter_type_enum,
118
- backing_file, hw_version, compat6, zeroed_grain,
119
- vmdk_co_create_opts_cb, &data, errp);
120
+ backing_file, hw_version, toolsversion, compat6,
121
+ zeroed_grain, vmdk_co_create_opts_cb, &data, errp);
122
123
exit:
124
g_free(backing_fmt);
125
g_free(adapter_type);
126
g_free(backing_file);
127
g_free(hw_version);
128
+ g_free(toolsversion);
129
g_free(fmt);
130
g_free(desc);
131
g_free(path);
132
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vmdk_co_create(BlockdevCreateOptions *create_options,
133
opts->adapter_type,
134
opts->backing_file,
135
opts->hwversion,
136
+ opts->toolsversion,
137
false,
138
opts->zeroed_grain,
139
vmdk_co_create_cb,
140
@@ -XXX,XX +XXX,XX @@ static QemuOptsList vmdk_create_opts = {
141
.help = "VMDK hardware version",
142
.def_value_str = "undefined"
143
},
144
+ {
145
+ .name = BLOCK_OPT_TOOLSVERSION,
146
+ .type = QEMU_OPT_STRING,
147
+ .help = "VMware guest tools version",
148
+ },
149
{
150
.name = BLOCK_OPT_SUBFMT,
151
.type = QEMU_OPT_STRING,
45
--
152
--
46
2.20.1
153
2.31.1
47
154
48
155
diff view generated by jsdifflib
1
From: Stefano Garzarella <sgarzare@redhat.com>
1
From: Thomas Huth <thuth@redhat.com>
2
2
3
In order to avoid migration issues, we enable DISCARD and
3
The code in vpc.c uses BDRVVPCState->footer.type in various places
4
WRITE_ZEROES features only for machine type >= 4.0
4
to decide whether the image is a fixed-size (VHD_FIXED) or a dynamic
5
(VHD_DYNAMIC) image. However, we never check that this field really
6
contains VHD_FIXED if we detected a fixed size image in vpc_open(),
7
so a wrong value here could cause quite some trouble during runtime.
5
8
6
As discussed with Michael S. Tsirkin and Stefan Hajnoczi on the
9
Suggested-by: Kevin Wolf <kwolf@redhat.com>
7
list [1], DISCARD operation should not have security implications
10
Signed-off-by: Thomas Huth <thuth@redhat.com>
8
(eg. page cache attacks), so we can enable it by default.
11
Message-Id: <20211012082702.792259-1-thuth@redhat.com>
12
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
13
---
14
block/vpc.c | 3 ++-
15
1 file changed, 2 insertions(+), 1 deletion(-)
9
16
10
[1] https://lists.gnu.org/archive/html/qemu-devel/2019-02/msg00504.html
17
diff --git a/block/vpc.c b/block/vpc.c
11
12
Suggested-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
13
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
14
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
15
Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
16
Acked-by: Pankaj Gupta <pagupta@redhat.com>
17
Message-id: 20190208134950.187665-4-sgarzare@redhat.com
18
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
19
---
20
hw/block/virtio-blk.c | 4 ++++
21
hw/core/machine.c | 2 ++
22
2 files changed, 6 insertions(+)
23
24
diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
25
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
26
--- a/hw/block/virtio-blk.c
19
--- a/block/vpc.c
27
+++ b/hw/block/virtio-blk.c
20
+++ b/block/vpc.c
28
@@ -XXX,XX +XXX,XX @@ static Property virtio_blk_properties[] = {
21
@@ -XXX,XX +XXX,XX @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags,
29
DEFINE_PROP_UINT16("queue-size", VirtIOBlock, conf.queue_size, 128),
22
if (ret < 0) {
30
DEFINE_PROP_LINK("iothread", VirtIOBlock, conf.iothread, TYPE_IOTHREAD,
23
goto fail;
31
IOThread *),
24
}
32
+ DEFINE_PROP_BIT64("discard", VirtIOBlock, host_features,
25
- if (strncmp(footer->creator, "conectix", 8)) {
33
+ VIRTIO_BLK_F_DISCARD, true),
26
+ if (strncmp(footer->creator, "conectix", 8) ||
34
+ DEFINE_PROP_BIT64("write-zeroes", VirtIOBlock, host_features,
27
+ be32_to_cpu(footer->type) != VHD_FIXED) {
35
+ VIRTIO_BLK_F_WRITE_ZEROES, true),
28
error_setg(errp, "invalid VPC image");
36
DEFINE_PROP_END_OF_LIST(),
29
ret = -EINVAL;
37
};
30
goto fail;
38
39
diff --git a/hw/core/machine.c b/hw/core/machine.c
40
index XXXXXXX..XXXXXXX 100644
41
--- a/hw/core/machine.c
42
+++ b/hw/core/machine.c
43
@@ -XXX,XX +XXX,XX @@ GlobalProperty hw_compat_3_1[] = {
44
{ "usb-kbd", "serial", "42" },
45
{ "usb-mouse", "serial", "42" },
46
{ "usb-kbd", "serial", "42" },
47
+ { "virtio-blk-device", "discard", "false" },
48
+ { "virtio-blk-device", "write-zeroes", "false" },
49
};
50
const size_t hw_compat_3_1_len = G_N_ELEMENTS(hw_compat_3_1);
51
52
--
31
--
53
2.20.1
32
2.31.1
54
33
55
34
diff view generated by jsdifflib