1
The following changes since commit b4fbe1f65a4769c09e6bf2d79fc84360f840f40e:
1
The following changes since commit 711c0418c8c1ce3a24346f058b001c4c5a2f0f81:
2
2
3
Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20190129' into staging (2019-01-29 12:00:19 +0000)
3
Merge remote-tracking branch 'remotes/philmd/tags/mips-20210702' into staging (2021-07-04 14:04:12 +0100)
4
4
5
are available in the Git repository at:
5
are available in the Git repository at:
6
6
7
https://git.xanclic.moe/XanClic/qemu.git tags/pull-block-2019-01-31
7
https://gitlab.com/stefanha/qemu.git tags/block-pull-request
8
8
9
for you to fetch changes up to 908b30164bbffad7430d551b2a03a8fbcaa631ef:
9
for you to fetch changes up to 9f460c64e13897117f35ffb61f6f5e0102cabc70:
10
10
11
iotests: Allow 147 to be run concurrently (2019-01-31 00:44:55 +0100)
11
block/io: Merge discard request alignments (2021-07-06 14:28:55 +0100)
12
12
13
----------------------------------------------------------------
13
----------------------------------------------------------------
14
Block patches:
14
Pull request
15
- New debugging QMP command to explore block graphs
16
- Converted DPRINTF()s to trace events
17
- Fixed qemu-io's use of getopt() for systems with optreset
18
- Minor NVMe emulation fixes
19
- An iotest fix
20
15
21
----------------------------------------------------------------
16
----------------------------------------------------------------
22
Laurent Vivier (4):
23
block/ssh: Convert from DPRINTF() macro to trace events
24
block/curl: Convert from DPRINTF() macro to trace events
25
block/file-posix: Convert from DPRINTF() macro to trace events
26
block/sheepdog: Convert from DPRINTF() macro to trace events
27
17
28
Li Qiang (3):
18
Akihiko Odaki (3):
29
nvme: use TYPE_NVME instead of constant string
19
block/file-posix: Optimize for macOS
30
nvme: ensure the num_queues is not zero
20
block: Add backend_defaults property
31
nvme: use pci_dev directly in nvme_realize
21
block/io: Merge discard request alignments
32
22
33
Max Reitz (3):
23
Stefan Hajnoczi (2):
34
iotests.py: Add qemu_nbd_pipe()
24
util/async: add a human-readable name to BHs for debugging
35
iotests: Bind qemu-nbd to localhost in 147
25
util/async: print leaked BH name when AioContext finalizes
36
iotests: Allow 147 to be run concurrently
37
26
38
Richard W.M. Jones (1):
27
include/block/aio.h | 31 ++++++++++++++++++++++---
39
qemu-io: Add generic function for reinitializing optind.
28
include/hw/block/block.h | 3 +++
40
29
include/qemu/main-loop.h | 4 +++-
41
Vladimir Sementsov-Ogievskiy (2):
30
block/file-posix.c | 27 ++++++++++++++++++++--
42
qapi: add x-debug-query-block-graph
31
block/io.c | 2 ++
43
scripts: add render_block_graph function for QEMUMachine
32
hw/block/block.c | 42 ++++++++++++++++++++++++++++++----
44
33
tests/unit/ptimer-test-stubs.c | 2 +-
45
configure | 14 ++++
34
util/async.c | 25 ++++++++++++++++----
46
qapi/block-core.json | 108 ++++++++++++++++++++++++
35
util/main-loop.c | 4 ++--
47
include/block/block.h | 1 +
36
tests/qemu-iotests/172.out | 38 ++++++++++++++++++++++++++++++
48
include/qemu/osdep.h | 16 ++++
37
10 files changed, 161 insertions(+), 17 deletions(-)
49
include/sysemu/block-backend.h | 2 +
50
block.c | 148 +++++++++++++++++++++++++++++++++
51
block/block-backend.c | 5 ++
52
block/curl.c | 29 ++-----
53
block/file-posix.c | 25 ++----
54
block/sheepdog.c | 47 ++++-------
55
block/ssh.c | 46 ++++------
56
blockdev.c | 5 ++
57
hw/block/nvme.c | 15 ++--
58
qemu-img.c | 2 +-
59
qemu-io-cmds.c | 2 +-
60
block/trace-events | 47 +++++++++++
61
scripts/render_block_graph.py | 120 ++++++++++++++++++++++++++
62
tests/qemu-iotests/147 | 98 +++++++++++++++-------
63
tests/qemu-iotests/iotests.py | 14 ++++
64
19 files changed, 608 insertions(+), 136 deletions(-)
65
create mode 100755 scripts/render_block_graph.py
66
38
67
--
39
--
68
2.20.1
40
2.31.1
69
41
70
diff view generated by jsdifflib
1
From: Laurent Vivier <lvivier@redhat.com>
1
It can be difficult to debug issues with BHs in production environments.
2
Although BHs can usually be identified by looking up their ->cb()
3
function pointer, this requires debug information for the program. It is
4
also not possible to print human-readable diagnostics about BHs because
5
they have no identifier.
2
6
3
Signed-off-by: Laurent Vivier <lvivier@redhat.com>
7
This patch adds a name to each BH. The name is not unique per instance
4
Reviewed-by: Richard W.M. Jones <rjones@redhat.com>
8
but differentiates between cb() functions, which is usually enough. It's
9
done by changing aio_bh_new() and friends to macros that stringify cb.
10
11
The next patch will use the name field when reporting leaked BHs.
12
13
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
5
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
14
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
6
Message-id: 20181213162727.17438-2-lvivier@redhat.com
15
Message-Id: <20210414200247.917496-2-stefanha@redhat.com>
7
[mreitz: Fixed type of ssh_{read,write}_return's parameter to be ssize_t
8
instead of size_t]
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
---
16
---
11
block/ssh.c | 46 +++++++++++++++++-----------------------------
17
include/block/aio.h | 31 ++++++++++++++++++++++++++++---
12
block/trace-events | 17 +++++++++++++++++
18
include/qemu/main-loop.h | 4 +++-
13
2 files changed, 34 insertions(+), 29 deletions(-)
19
tests/unit/ptimer-test-stubs.c | 2 +-
20
util/async.c | 9 +++++++--
21
util/main-loop.c | 4 ++--
22
5 files changed, 41 insertions(+), 9 deletions(-)
14
23
15
diff --git a/block/ssh.c b/block/ssh.c
24
diff --git a/include/block/aio.h b/include/block/aio.h
16
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
17
--- a/block/ssh.c
26
--- a/include/block/aio.h
18
+++ b/block/ssh.c
27
+++ b/include/block/aio.h
19
@@ -XXX,XX +XXX,XX @@
28
@@ -XXX,XX +XXX,XX @@ void aio_context_acquire(AioContext *ctx);
20
#include "qapi/qmp/qstring.h"
29
/* Relinquish ownership of the AioContext. */
21
#include "qapi/qobject-input-visitor.h"
30
void aio_context_release(AioContext *ctx);
22
#include "qapi/qobject-output-visitor.h"
31
23
+#include "trace.h"
32
+/**
24
33
+ * aio_bh_schedule_oneshot_full: Allocate a new bottom half structure that will
25
-/* DEBUG_SSH=1 enables the DPRINTF (debugging printf) statements in
34
+ * run only once and as soon as possible.
26
- * this block driver code.
35
+ *
27
- *
36
+ * @name: A human-readable identifier for debugging purposes.
28
+/*
37
+ */
29
* TRACE_LIBSSH2=<bitmask> enables tracing in libssh2 itself. Note
38
+void aio_bh_schedule_oneshot_full(AioContext *ctx, QEMUBHFunc *cb, void *opaque,
30
* that this requires that libssh2 was specially compiled with the
39
+ const char *name);
31
* `./configure --enable-debug' option, so most likely you will have
40
+
32
* to compile it yourself. The meaning of <bitmask> is described
41
/**
33
* here: http://www.libssh2.org/libssh2_trace.html
42
* aio_bh_schedule_oneshot: Allocate a new bottom half structure that will run
43
* only once and as soon as possible.
44
+ *
45
+ * A convenience wrapper for aio_bh_schedule_oneshot_full() that uses cb as the
46
+ * name string.
34
*/
47
*/
35
-#define DEBUG_SSH 0
48
-void aio_bh_schedule_oneshot(AioContext *ctx, QEMUBHFunc *cb, void *opaque);
36
#define TRACE_LIBSSH2 0 /* or try: LIBSSH2_TRACE_SFTP */
49
+#define aio_bh_schedule_oneshot(ctx, cb, opaque) \
37
50
+ aio_bh_schedule_oneshot_full((ctx), (cb), (opaque), (stringify(cb)))
38
-#define DPRINTF(fmt, ...) \
51
39
- do { \
52
/**
40
- if (DEBUG_SSH) { \
53
- * aio_bh_new: Allocate a new bottom half structure.
41
- fprintf(stderr, "ssh: %-15s " fmt "\n", \
54
+ * aio_bh_new_full: Allocate a new bottom half structure.
42
- __func__, ##__VA_ARGS__); \
55
*
43
- } \
56
* Bottom halves are lightweight callbacks whose invocation is guaranteed
44
- } while (0)
57
* to be wait-free, thread-safe and signal-safe. The #QEMUBH structure
45
-
58
* is opaque and must be allocated prior to its use.
46
typedef struct BDRVSSHState {
59
+ *
47
/* Coroutine. */
60
+ * @name: A human-readable identifier for debugging purposes.
48
CoMutex lock;
61
*/
49
@@ -XXX,XX +XXX,XX @@ static int check_host_key_knownhosts(BDRVSSHState *s,
62
-QEMUBH *aio_bh_new(AioContext *ctx, QEMUBHFunc *cb, void *opaque);
50
switch (r) {
63
+QEMUBH *aio_bh_new_full(AioContext *ctx, QEMUBHFunc *cb, void *opaque,
51
case LIBSSH2_KNOWNHOST_CHECK_MATCH:
64
+ const char *name);
52
/* OK */
65
+
53
- DPRINTF("host key OK: %s", found->key);
66
+/**
54
+ trace_ssh_check_host_key_knownhosts(found->key);
67
+ * aio_bh_new: Allocate a new bottom half structure
55
break;
68
+ *
56
case LIBSSH2_KNOWNHOST_CHECK_MISMATCH:
69
+ * A convenience wrapper for aio_bh_new_full() that uses the cb as the name
57
ret = -EINVAL;
70
+ * string.
58
@@ -XXX,XX +XXX,XX @@ static int connect_to_ssh(BDRVSSHState *s, BlockdevOptionsSsh *opts,
71
+ */
59
}
72
+#define aio_bh_new(ctx, cb, opaque) \
60
73
+ aio_bh_new_full((ctx), (cb), (opaque), (stringify(cb)))
61
/* Open the remote file. */
74
62
- DPRINTF("opening file %s flags=0x%x creat_mode=0%o",
75
/**
63
- opts->path, ssh_flags, creat_mode);
76
* aio_notify: Force processing of pending events.
64
+ trace_ssh_connect_to_ssh(opts->path, ssh_flags, creat_mode);
77
diff --git a/include/qemu/main-loop.h b/include/qemu/main-loop.h
65
s->sftp_handle = libssh2_sftp_open(s->sftp, opts->path, ssh_flags,
78
index XXXXXXX..XXXXXXX 100644
66
creat_mode);
79
--- a/include/qemu/main-loop.h
67
if (!s->sftp_handle) {
80
+++ b/include/qemu/main-loop.h
68
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn ssh_co_create_opts(const char *filename, QemuOpts *opts,
81
@@ -XXX,XX +XXX,XX @@ void qemu_cond_timedwait_iothread(QemuCond *cond, int ms);
69
/* Get desired file size. */
82
70
ssh_opts->size = ROUND_UP(qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0),
83
void qemu_fd_register(int fd);
71
BDRV_SECTOR_SIZE);
84
72
- DPRINTF("total_size=%" PRIi64, ssh_opts->size);
85
-QEMUBH *qemu_bh_new(QEMUBHFunc *cb, void *opaque);
73
+ trace_ssh_co_create_opts(ssh_opts->size);
86
+#define qemu_bh_new(cb, opaque) \
74
87
+ qemu_bh_new_full((cb), (opaque), (stringify(cb)))
75
uri_options = qdict_new();
88
+QEMUBH *qemu_bh_new_full(QEMUBHFunc *cb, void *opaque, const char *name);
76
ret = parse_uri(filename, uri_options, errp);
89
void qemu_bh_schedule_idle(QEMUBH *bh);
77
@@ -XXX,XX +XXX,XX @@ static void restart_coroutine(void *opaque)
90
78
BDRVSSHState *s = bs->opaque;
91
enum {
79
AioContext *ctx = bdrv_get_aio_context(bs);
92
diff --git a/tests/unit/ptimer-test-stubs.c b/tests/unit/ptimer-test-stubs.c
80
93
index XXXXXXX..XXXXXXX 100644
81
- DPRINTF("co=%p", restart->co);
94
--- a/tests/unit/ptimer-test-stubs.c
82
+ trace_ssh_restart_coroutine(restart->co);
95
+++ b/tests/unit/ptimer-test-stubs.c
83
aio_set_fd_handler(ctx, s->sock, false, NULL, NULL, NULL, NULL);
96
@@ -XXX,XX +XXX,XX @@ int64_t qemu_clock_deadline_ns_all(QEMUClockType type, int attr_mask)
84
97
return deadline;
85
aio_co_wake(restart->co);
86
@@ -XXX,XX +XXX,XX @@ static coroutine_fn void co_yield(BDRVSSHState *s, BlockDriverState *bs)
87
wr_handler = restart_coroutine;
88
}
89
90
- DPRINTF("s->sock=%d rd_handler=%p wr_handler=%p", s->sock,
91
- rd_handler, wr_handler);
92
+ trace_ssh_co_yield(s->sock, rd_handler, wr_handler);
93
94
aio_set_fd_handler(bdrv_get_aio_context(bs), s->sock,
95
false, rd_handler, wr_handler, NULL, &restart);
96
qemu_coroutine_yield();
97
- DPRINTF("s->sock=%d - back", s->sock);
98
+ trace_ssh_co_yield_back(s->sock);
99
}
98
}
100
99
101
/* SFTP has a function `libssh2_sftp_seek64' which seeks to a position
100
-QEMUBH *qemu_bh_new(QEMUBHFunc *cb, void *opaque)
102
@@ -XXX,XX +XXX,XX @@ static void ssh_seek(BDRVSSHState *s, int64_t offset, int flags)
101
+QEMUBH *qemu_bh_new_full(QEMUBHFunc *cb, void *opaque, const char *name)
103
bool force = (flags & SSH_SEEK_FORCE) != 0;
104
105
if (force || op_read != s->offset_op_read || offset != s->offset) {
106
- DPRINTF("seeking to offset=%" PRIi64, offset);
107
+ trace_ssh_seek(offset);
108
libssh2_sftp_seek64(s->sftp_handle, offset);
109
s->offset = offset;
110
s->offset_op_read = op_read;
111
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int ssh_read(BDRVSSHState *s, BlockDriverState *bs,
112
char *buf, *end_of_vec;
113
struct iovec *i;
114
115
- DPRINTF("offset=%" PRIi64 " size=%zu", offset, size);
116
+ trace_ssh_read(offset, size);
117
118
ssh_seek(s, offset, SSH_SEEK_READ);
119
120
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int ssh_read(BDRVSSHState *s, BlockDriverState *bs,
121
*/
122
for (got = 0; got < size; ) {
123
again:
124
- DPRINTF("sftp_read buf=%p size=%zu", buf, end_of_vec - buf);
125
+ trace_ssh_read_buf(buf, end_of_vec - buf);
126
r = libssh2_sftp_read(s->sftp_handle, buf, end_of_vec - buf);
127
- DPRINTF("sftp_read returned %zd", r);
128
+ trace_ssh_read_return(r);
129
130
if (r == LIBSSH2_ERROR_EAGAIN || r == LIBSSH2_ERROR_TIMEOUT) {
131
co_yield(s, bs);
132
@@ -XXX,XX +XXX,XX @@ static int ssh_write(BDRVSSHState *s, BlockDriverState *bs,
133
char *buf, *end_of_vec;
134
struct iovec *i;
135
136
- DPRINTF("offset=%" PRIi64 " size=%zu", offset, size);
137
+ trace_ssh_write(offset, size);
138
139
ssh_seek(s, offset, SSH_SEEK_WRITE);
140
141
@@ -XXX,XX +XXX,XX @@ static int ssh_write(BDRVSSHState *s, BlockDriverState *bs,
142
143
for (written = 0; written < size; ) {
144
again:
145
- DPRINTF("sftp_write buf=%p size=%zu", buf, end_of_vec - buf);
146
+ trace_ssh_write_buf(buf, end_of_vec - buf);
147
r = libssh2_sftp_write(s->sftp_handle, buf, end_of_vec - buf);
148
- DPRINTF("sftp_write returned %zd", r);
149
+ trace_ssh_write_return(r);
150
151
if (r == LIBSSH2_ERROR_EAGAIN || r == LIBSSH2_ERROR_TIMEOUT) {
152
co_yield(s, bs);
153
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int ssh_flush(BDRVSSHState *s, BlockDriverState *bs)
154
{
102
{
155
int r;
103
QEMUBH *bh = g_new(QEMUBH, 1);
156
104
157
- DPRINTF("fsync");
105
diff --git a/util/async.c b/util/async.c
158
+ trace_ssh_flush();
106
index XXXXXXX..XXXXXXX 100644
159
again:
107
--- a/util/async.c
160
r = libssh2_sftp_fsync(s->sftp_handle);
108
+++ b/util/async.c
161
if (r == LIBSSH2_ERROR_EAGAIN || r == LIBSSH2_ERROR_TIMEOUT) {
109
@@ -XXX,XX +XXX,XX @@ enum {
162
@@ -XXX,XX +XXX,XX @@ static int64_t ssh_getlength(BlockDriverState *bs)
110
163
111
struct QEMUBH {
164
/* Note we cannot make a libssh2 call here. */
112
AioContext *ctx;
165
length = (int64_t) s->attrs.filesize;
113
+ const char *name;
166
- DPRINTF("length=%" PRIi64, length);
114
QEMUBHFunc *cb;
167
+ trace_ssh_getlength(length);
115
void *opaque;
168
116
QSLIST_ENTRY(QEMUBH) next;
169
return length;
117
@@ -XXX,XX +XXX,XX @@ static QEMUBH *aio_bh_dequeue(BHList *head, unsigned *flags)
118
return bh;
170
}
119
}
171
diff --git a/block/trace-events b/block/trace-events
120
121
-void aio_bh_schedule_oneshot(AioContext *ctx, QEMUBHFunc *cb, void *opaque)
122
+void aio_bh_schedule_oneshot_full(AioContext *ctx, QEMUBHFunc *cb,
123
+ void *opaque, const char *name)
124
{
125
QEMUBH *bh;
126
bh = g_new(QEMUBH, 1);
127
@@ -XXX,XX +XXX,XX @@ void aio_bh_schedule_oneshot(AioContext *ctx, QEMUBHFunc *cb, void *opaque)
128
.ctx = ctx,
129
.cb = cb,
130
.opaque = opaque,
131
+ .name = name,
132
};
133
aio_bh_enqueue(bh, BH_SCHEDULED | BH_ONESHOT);
134
}
135
136
-QEMUBH *aio_bh_new(AioContext *ctx, QEMUBHFunc *cb, void *opaque)
137
+QEMUBH *aio_bh_new_full(AioContext *ctx, QEMUBHFunc *cb, void *opaque,
138
+ const char *name)
139
{
140
QEMUBH *bh;
141
bh = g_new(QEMUBH, 1);
142
@@ -XXX,XX +XXX,XX @@ QEMUBH *aio_bh_new(AioContext *ctx, QEMUBHFunc *cb, void *opaque)
143
.ctx = ctx,
144
.cb = cb,
145
.opaque = opaque,
146
+ .name = name,
147
};
148
return bh;
149
}
150
diff --git a/util/main-loop.c b/util/main-loop.c
172
index XXXXXXX..XXXXXXX 100644
151
index XXXXXXX..XXXXXXX 100644
173
--- a/block/trace-events
152
--- a/util/main-loop.c
174
+++ b/block/trace-events
153
+++ b/util/main-loop.c
175
@@ -XXX,XX +XXX,XX @@ iscsi_xcopy(void *src_lun, uint64_t src_off, void *dst_lun, uint64_t dst_off, ui
154
@@ -XXX,XX +XXX,XX @@ void main_loop_wait(int nonblocking)
176
# block/nbd-client.c
155
177
nbd_read_reply_entry_fail(int ret, const char *err) "ret = %d, err: %s"
156
/* Functions to operate on the main QEMU AioContext. */
178
nbd_co_request_fail(uint64_t from, uint32_t len, uint64_t handle, uint16_t flags, uint16_t type, const char *name, int ret, const char *err) "Request failed { .from = %" PRIu64", .len = %" PRIu32 ", .handle = %" PRIu64 ", .flags = 0x%" PRIx16 ", .type = %" PRIu16 " (%s) } ret = %d, err: %s"
157
179
+
158
-QEMUBH *qemu_bh_new(QEMUBHFunc *cb, void *opaque)
180
+# block/ssh.c
159
+QEMUBH *qemu_bh_new_full(QEMUBHFunc *cb, void *opaque, const char *name)
181
+ssh_restart_coroutine(void *co) "co=%p"
160
{
182
+ssh_flush(void) "fsync"
161
- return aio_bh_new(qemu_aio_context, cb, opaque);
183
+ssh_check_host_key_knownhosts(const char *key) "host key OK: %s"
162
+ return aio_bh_new_full(qemu_aio_context, cb, opaque, name);
184
+ssh_connect_to_ssh(char *path, int flags, int mode) "opening file %s flags=0x%x creat_mode=0%o"
163
}
185
+ssh_co_yield(int sock, void *rd_handler, void *wr_handler) "s->sock=%d rd_handler=%p wr_handler=%p"
164
186
+ssh_co_yield_back(int sock) "s->sock=%d - back"
165
/*
187
+ssh_getlength(int64_t length) "length=%" PRIi64
188
+ssh_co_create_opts(uint64_t size) "total_size=%" PRIu64
189
+ssh_read(int64_t offset, size_t size) "offset=%" PRIi64 " size=%zu"
190
+ssh_read_buf(void *buf, size_t size) "sftp_read buf=%p size=%zu"
191
+ssh_read_return(ssize_t ret) "sftp_read returned %zd"
192
+ssh_write(int64_t offset, size_t size) "offset=%" PRIi64 " size=%zu"
193
+ssh_write_buf(void *buf, size_t size) "sftp_write buf=%p size=%zu"
194
+ssh_write_return(ssize_t ret) "sftp_write returned %zd"
195
+ssh_seek(int64_t offset) "seeking to offset=%" PRIi64
196
--
166
--
197
2.20.1
167
2.31.1
198
168
199
diff view generated by jsdifflib
1
To do this, we need to allow creating the NBD server on various ports
1
BHs must be deleted before the AioContext is finalized. If not, it's a
2
instead of a single one (which may not even work if you run just one
2
bug and probably indicates that some part of the program still expects
3
instance, because something entirely else might be using that port).
3
the BH to run in the future. That can lead to memory leaks, inconsistent
4
state, or just hangs.
4
5
5
So we just pick a random port in [32768, 32768 + 1024) and try to create
6
Unfortunately the assert(flags & BH_DELETED) call in aio_ctx_finalize()
6
a server there. If that fails, we just retry until something sticks.
7
is difficult to debug because the assertion failure contains no
8
information about the BH!
7
9
8
For the IPv6 test, we need a different range, though (just above that
10
Use the QEMUBH name field added in the previous patch to show a useful
9
one). This is because "localhost" resolves to both 127.0.0.1 and ::1.
11
error when a leaked BH is detected.
10
This means that if you bind to it, it will bind to both, if possible, or
11
just one if the other is already in use. Therefore, if the IPv6 test
12
has already taken [::1]:some_port and we then try to take
13
localhost:some_port, that will work -- only the second server will be
14
bound to 127.0.0.1:some_port alone and not [::1]:some_port in addition.
15
So we have two different servers on the same port, one for IPv4 and one
16
for IPv6.
17
12
18
But when we then try to connect to the server through
13
Suggested-by: Eric Ernst <eric.g.ernst@gmail.com>
19
localhost:some_port, we will always end up at the IPv6 one (as long as
14
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
20
it is up), and this may not be the one we want.
15
Message-Id: <20210414200247.917496-3-stefanha@redhat.com>
16
---
17
util/async.c | 16 ++++++++++++++--
18
1 file changed, 14 insertions(+), 2 deletions(-)
21
19
22
Thus, we must make sure not to create an IPv6-only NBD server on the
20
diff --git a/util/async.c b/util/async.c
23
same port as a normal "dual-stack" NBD server -- which is done by using
21
index XXXXXXX..XXXXXXX 100644
24
distinct port ranges, as explained above.
22
--- a/util/async.c
23
+++ b/util/async.c
24
@@ -XXX,XX +XXX,XX @@ aio_ctx_finalize(GSource *source)
25
assert(QSIMPLEQ_EMPTY(&ctx->bh_slice_list));
26
27
while ((bh = aio_bh_dequeue(&ctx->bh_list, &flags))) {
28
- /* qemu_bh_delete() must have been called on BHs in this AioContext */
29
- assert(flags & BH_DELETED);
30
+ /*
31
+ * qemu_bh_delete() must have been called on BHs in this AioContext. In
32
+ * many cases memory leaks, hangs, or inconsistent state occur when a
33
+ * BH is leaked because something still expects it to run.
34
+ *
35
+ * If you hit this, fix the lifecycle of the BH so that
36
+ * qemu_bh_delete() and any associated cleanup is called before the
37
+ * AioContext is finalized.
38
+ */
39
+ if (unlikely(!(flags & BH_DELETED))) {
40
+ fprintf(stderr, "%s: BH '%s' leaked, aborting...\n",
41
+ __func__, bh->name);
42
+ abort();
43
+ }
44
45
g_free(bh);
46
}
47
--
48
2.31.1
25
49
26
Signed-off-by: Max Reitz <mreitz@redhat.com>
27
Message-id: 20181221234750.23577-4-mreitz@redhat.com
28
Reviewed-by: John Snow <jsnow@redhat.com>
29
Signed-off-by: Max Reitz <mreitz@redhat.com>
30
---
31
tests/qemu-iotests/147 | 98 +++++++++++++++++++++++++++++-------------
32
1 file changed, 68 insertions(+), 30 deletions(-)
33
34
diff --git a/tests/qemu-iotests/147 b/tests/qemu-iotests/147
35
index XXXXXXX..XXXXXXX 100755
36
--- a/tests/qemu-iotests/147
37
+++ b/tests/qemu-iotests/147
38
@@ -XXX,XX +XXX,XX @@
39
#
40
41
import os
42
+import random
43
import socket
44
import stat
45
import time
46
import iotests
47
-from iotests import cachemode, imgfmt, qemu_img, qemu_nbd
48
+from iotests import cachemode, imgfmt, qemu_img, qemu_nbd, qemu_nbd_pipe
49
50
-NBD_PORT = 10811
51
+NBD_PORT_START = 32768
52
+NBD_PORT_END = NBD_PORT_START + 1024
53
+NBD_IPV6_PORT_START = NBD_PORT_END
54
+NBD_IPV6_PORT_END = NBD_IPV6_PORT_START + 1024
55
56
test_img = os.path.join(iotests.test_dir, 'test.img')
57
unix_socket = os.path.join(iotests.test_dir, 'nbd.socket')
58
@@ -XXX,XX +XXX,XX @@ class QemuNBD(NBDBlockdevAddBase):
59
except OSError:
60
pass
61
62
+ def _try_server_up(self, *args):
63
+ status, msg = qemu_nbd_pipe('-f', imgfmt, test_img, *args)
64
+ if status == 0:
65
+ return True
66
+ if 'Address already in use' in msg:
67
+ return False
68
+ self.fail(msg)
69
+
70
def _server_up(self, *args):
71
- self.assertEqual(qemu_nbd('-f', imgfmt, test_img, *args), 0)
72
+ self.assertTrue(self._try_server_up(*args))
73
74
def test_inet(self):
75
- self._server_up('-b', 'localhost', '-p', str(NBD_PORT))
76
+ while True:
77
+ nbd_port = random.randrange(NBD_PORT_START, NBD_PORT_END)
78
+ if self._try_server_up('-b', 'localhost', '-p', str(nbd_port)):
79
+ break
80
+
81
address = { 'type': 'inet',
82
'data': {
83
'host': 'localhost',
84
- 'port': str(NBD_PORT)
85
+ 'port': str(nbd_port)
86
} }
87
- self.client_test('nbd://localhost:%i' % NBD_PORT,
88
+ self.client_test('nbd://localhost:%i' % nbd_port,
89
flatten_sock_addr(address))
90
91
def test_unix(self):
92
@@ -XXX,XX +XXX,XX @@ class BuiltinNBD(NBDBlockdevAddBase):
93
except OSError:
94
pass
95
96
- def _server_up(self, address, export_name=None, export_name2=None):
97
+ # Returns False on EADDRINUSE; fails an assertion on other errors.
98
+ # Returns True on success.
99
+ def _try_server_up(self, address, export_name=None, export_name2=None):
100
result = self.server.qmp('nbd-server-start', addr=address)
101
+ if 'error' in result and \
102
+ 'Address already in use' in result['error']['desc']:
103
+ return False
104
self.assert_qmp(result, 'return', {})
105
106
if export_name is None:
107
@@ -XXX,XX +XXX,XX @@ class BuiltinNBD(NBDBlockdevAddBase):
108
name=export_name2)
109
self.assert_qmp(result, 'return', {})
110
111
+ return True
112
+
113
+ def _server_up(self, address, export_name=None, export_name2=None):
114
+ self.assertTrue(self._try_server_up(address, export_name, export_name2))
115
116
def _server_down(self):
117
result = self.server.qmp('nbd-server-stop')
118
self.assert_qmp(result, 'return', {})
119
120
def do_test_inet(self, export_name=None):
121
- address = { 'type': 'inet',
122
- 'data': {
123
- 'host': 'localhost',
124
- 'port': str(NBD_PORT)
125
- } }
126
- self._server_up(address, export_name)
127
+ while True:
128
+ nbd_port = random.randrange(NBD_PORT_START, NBD_PORT_END)
129
+ address = { 'type': 'inet',
130
+ 'data': {
131
+ 'host': 'localhost',
132
+ 'port': str(nbd_port)
133
+ } }
134
+ if self._try_server_up(address, export_name):
135
+ break
136
+
137
export_name = export_name or 'nbd-export'
138
- self.client_test('nbd://localhost:%i/%s' % (NBD_PORT, export_name),
139
+ self.client_test('nbd://localhost:%i/%s' % (nbd_port, export_name),
140
flatten_sock_addr(address), export_name)
141
self._server_down()
142
143
@@ -XXX,XX +XXX,XX @@ class BuiltinNBD(NBDBlockdevAddBase):
144
self.do_test_inet('shadow')
145
146
def test_inet_two_exports(self):
147
- address = { 'type': 'inet',
148
- 'data': {
149
- 'host': 'localhost',
150
- 'port': str(NBD_PORT)
151
- } }
152
- self._server_up(address, 'exp1', 'exp2')
153
- self.client_test('nbd://localhost:%i/%s' % (NBD_PORT, 'exp1'),
154
+ while True:
155
+ nbd_port = random.randrange(NBD_PORT_START, NBD_PORT_END)
156
+ address = { 'type': 'inet',
157
+ 'data': {
158
+ 'host': 'localhost',
159
+ 'port': str(nbd_port)
160
+ } }
161
+ if self._try_server_up(address, 'exp1', 'exp2'):
162
+ break
163
+
164
+ self.client_test('nbd://localhost:%i/%s' % (nbd_port, 'exp1'),
165
flatten_sock_addr(address), 'exp1', 'node1', False)
166
- self.client_test('nbd://localhost:%i/%s' % (NBD_PORT, 'exp2'),
167
+ self.client_test('nbd://localhost:%i/%s' % (nbd_port, 'exp2'),
168
flatten_sock_addr(address), 'exp2', 'node2', False)
169
result = self.vm.qmp('blockdev-del', node_name='node1')
170
self.assert_qmp(result, 'return', {})
171
@@ -XXX,XX +XXX,XX @@ class BuiltinNBD(NBDBlockdevAddBase):
172
except socket.gaierror:
173
# IPv6 not available, skip
174
return
175
- address = { 'type': 'inet',
176
- 'data': {
177
- 'host': '::1',
178
- 'port': str(NBD_PORT),
179
- 'ipv4': False,
180
- 'ipv6': True
181
- } }
182
+
183
+ while True:
184
+ nbd_port = random.randrange(NBD_IPV6_PORT_START, NBD_IPV6_PORT_END)
185
+ address = { 'type': 'inet',
186
+ 'data': {
187
+ 'host': '::1',
188
+ 'port': str(nbd_port),
189
+ 'ipv4': False,
190
+ 'ipv6': True
191
+ } }
192
+ if self._try_server_up(address):
193
+ break
194
+
195
filename = { 'driver': 'raw',
196
'file': {
197
'driver': 'nbd',
198
'export': 'nbd-export',
199
'server': flatten_sock_addr(address)
200
} }
201
- self._server_up(address)
202
self.client_test(filename, flatten_sock_addr(address), 'nbd-export')
203
self._server_down()
204
205
--
206
2.20.1
207
208
diff view generated by jsdifflib
1
From: Laurent Vivier <lvivier@redhat.com>
1
From: Akihiko Odaki <akihiko.odaki@gmail.com>
2
2
3
Signed-off-by: Laurent Vivier <lvivier@redhat.com>
3
This commit introduces "punch hole" operation and optimizes transfer
4
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
4
block size for macOS.
5
Message-id: 20181213162727.17438-4-lvivier@redhat.com
5
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
6
Thanks to Konstantin Nazarov for detailed analysis of a flaw in an
7
old version of this change:
8
https://gist.github.com/akihikodaki/87df4149e7ca87f18dc56807ec5a1bc5#gistcomment-3654667
9
10
Signed-off-by: Akihiko Odaki <akihiko.odaki@gmail.com>
11
Message-id: 20210705130458.97642-1-akihiko.odaki@gmail.com
12
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
7
---
13
---
8
block/file-posix.c | 25 ++++++-------------------
14
block/file-posix.c | 27 +++++++++++++++++++++++++--
9
block/trace-events | 7 +++++++
15
1 file changed, 25 insertions(+), 2 deletions(-)
10
2 files changed, 13 insertions(+), 19 deletions(-)
11
16
12
diff --git a/block/file-posix.c b/block/file-posix.c
17
diff --git a/block/file-posix.c b/block/file-posix.c
13
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
14
--- a/block/file-posix.c
19
--- a/block/file-posix.c
15
+++ b/block/file-posix.c
20
+++ b/block/file-posix.c
16
@@ -XXX,XX +XXX,XX @@
21
@@ -XXX,XX +XXX,XX @@
17
#include <xfs/xfs.h>
22
#if defined(HAVE_HOST_BLOCK_DEVICE)
23
#include <paths.h>
24
#include <sys/param.h>
25
+#include <sys/mount.h>
26
#include <IOKit/IOKitLib.h>
27
#include <IOKit/IOBSD.h>
28
#include <IOKit/storage/IOMediaBSDClient.h>
29
@@ -XXX,XX +XXX,XX @@ static void raw_refresh_limits(BlockDriverState *bs, Error **errp)
30
return;
31
}
32
33
+#if defined(__APPLE__) && (__MACH__)
34
+ struct statfs buf;
35
+
36
+ if (!fstatfs(s->fd, &buf)) {
37
+ bs->bl.opt_transfer = buf.f_iosize;
38
+ bs->bl.pdiscard_alignment = buf.f_bsize;
39
+ }
40
+#endif
41
+
42
if (bs->sg || S_ISBLK(st.st_mode)) {
43
int ret = hdev_get_max_hw_transfer(s->fd, &st);
44
45
@@ -XXX,XX +XXX,XX @@ out:
46
}
47
}
48
49
+#if defined(CONFIG_FALLOCATE) || defined(BLKZEROOUT) || defined(BLKDISCARD)
50
static int translate_err(int err)
51
{
52
if (err == -ENODEV || err == -ENOSYS || err == -EOPNOTSUPP ||
53
@@ -XXX,XX +XXX,XX @@ static int translate_err(int err)
54
}
55
return err;
56
}
57
+#endif
58
59
#ifdef CONFIG_FALLOCATE
60
static int do_fallocate(int fd, int mode, off_t offset, off_t len)
61
@@ -XXX,XX +XXX,XX @@ static int handle_aiocb_discard(void *opaque)
62
}
63
} while (errno == EINTR);
64
65
- ret = -errno;
66
+ ret = translate_err(-errno);
18
#endif
67
#endif
19
68
} else {
20
-//#define DEBUG_BLOCK
69
#ifdef CONFIG_FALLOCATE_PUNCH_HOLE
21
-
70
ret = do_fallocate(s->fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
22
-#ifdef DEBUG_BLOCK
71
aiocb->aio_offset, aiocb->aio_nbytes);
23
-# define DEBUG_BLOCK_PRINT 1
72
+ ret = translate_err(-errno);
24
-#else
73
+#elif defined(__APPLE__) && (__MACH__)
25
-# define DEBUG_BLOCK_PRINT 0
74
+ fpunchhole_t fpunchhole;
26
-#endif
75
+ fpunchhole.fp_flags = 0;
27
-#define DPRINTF(fmt, ...) \
76
+ fpunchhole.reserved = 0;
28
-do { \
77
+ fpunchhole.fp_offset = aiocb->aio_offset;
29
- if (DEBUG_BLOCK_PRINT) { \
78
+ fpunchhole.fp_length = aiocb->aio_nbytes;
30
- printf(fmt, ## __VA_ARGS__); \
79
+ if (fcntl(s->fd, F_PUNCHHOLE, &fpunchhole) == -1) {
31
- } \
80
+ ret = errno == ENODEV ? -ENOTSUP : -errno;
32
-} while (0)
81
+ } else {
33
+#include "trace.h"
82
+ ret = 0;
34
83
+ }
35
/* OS X does not have O_DSYNC */
84
#endif
36
#ifndef O_DSYNC
37
@@ -XXX,XX +XXX,XX @@ static int xfs_write_zeroes(BDRVRawState *s, int64_t offset, uint64_t bytes)
38
39
if (xfsctl(NULL, s->fd, XFS_IOC_ZERO_RANGE, &fl) < 0) {
40
err = errno;
41
- DPRINTF("cannot write zero range (%s)\n", strerror(errno));
42
+ trace_file_xfs_write_zeroes(strerror(errno));
43
return -err;
44
}
85
}
45
86
46
@@ -XXX,XX +XXX,XX @@ static int xfs_discard(BDRVRawState *s, int64_t offset, uint64_t bytes)
87
- ret = translate_err(ret);
47
88
if (ret == -ENOTSUP) {
48
if (xfsctl(NULL, s->fd, XFS_IOC_UNRESVSP64, &fl) < 0) {
89
s->has_discard = false;
49
err = errno;
50
- DPRINTF("cannot punch hole (%s)\n", strerror(errno));
51
+ trace_file_xfs_discard(strerror(errno));
52
return -err;
53
}
90
}
54
55
@@ -XXX,XX +XXX,XX @@ static char *FindEjectableOpticalMedia(io_iterator_t *mediaIterator)
56
57
/* If a match was found, leave the loop */
58
if (*mediaIterator != 0) {
59
- DPRINTF("Matching using %s\n", matching_array[index]);
60
+ trace_file_FindEjectableOpticalMedia(matching_array[index]);
61
mediaType = g_strdup(matching_array[index]);
62
break;
63
}
64
@@ -XXX,XX +XXX,XX @@ static bool setup_cdrom(char *bsd_path, Error **errp)
65
if (partition_found == false) {
66
error_setg(errp, "Failed to find a working partition on disc");
67
} else {
68
- DPRINTF("Using %s as optical disc\n", test_partition);
69
+ trace_file_setup_cdrom(test_partition);
70
pstrcpy(bsd_path, MAXPATHLEN, test_partition);
71
}
72
return partition_found;
73
@@ -XXX,XX +XXX,XX @@ static bool hdev_is_sg(BlockDriverState *bs)
74
75
ret = ioctl(s->fd, SG_GET_SCSI_ID, &scsiid);
76
if (ret >= 0) {
77
- DPRINTF("SG device found: type=%d, version=%d\n",
78
- scsiid.scsi_type, sg_version);
79
+ trace_file_hdev_is_sg(scsiid.scsi_type, sg_version);
80
return true;
81
}
82
83
diff --git a/block/trace-events b/block/trace-events
84
index XXXXXXX..XXXXXXX 100644
85
--- a/block/trace-events
86
+++ b/block/trace-events
87
@@ -XXX,XX +XXX,XX @@ curl_open(const char *file) "opening %s"
88
curl_open_size(uint64_t size) "size = %" PRIu64
89
curl_setup_preadv(uint64_t bytes, uint64_t start, const char *range) "reading %" PRIu64 " at %" PRIu64 " (%s)"
90
curl_close(void) "close"
91
+
92
+# block/file-posix.c
93
+file_xfs_write_zeroes(const char *error) "cannot write zero range (%s)"
94
+file_xfs_discard(const char *error) "cannot punch hole (%s)"
95
+file_FindEjectableOpticalMedia(const char *media) "Matching using %s"
96
+file_setup_cdrom(const char *partition) "Using %s as optical disc"
97
+file_hdev_is_sg(int type, int version) "SG device found: type=%d, version=%d"
98
--
91
--
99
2.20.1
92
2.31.1
100
93
101
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
From: Akihiko Odaki <akihiko.odaki@gmail.com>
2
2
3
Add a new command, returning block nodes (and their users) graph.
3
backend_defaults property allow users to control if default block
4
4
properties should be decided with backend information.
5
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
5
6
Message-id: 20181221170909.25584-2-vsementsov@virtuozzo.com
6
If it is off, any backend information will be discarded, which is
7
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
suitable if you plan to perform live migration to a different disk backend.
8
9
If it is on, a block device may utilize backend information more
10
aggressively.
11
12
By default, it is auto, which uses backend information for block
13
sizes and ignores the others, which is consistent with the older
14
versions.
15
16
Signed-off-by: Akihiko Odaki <akihiko.odaki@gmail.com>
17
Message-id: 20210705130458.97642-2-akihiko.odaki@gmail.com
18
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
8
---
19
---
9
qapi/block-core.json | 108 ++++++++++++++++++++++++
20
include/hw/block/block.h | 3 +++
10
include/block/block.h | 1 +
21
hw/block/block.c | 42 ++++++++++++++++++++++++++++++++++----
11
include/sysemu/block-backend.h | 2 +
22
tests/qemu-iotests/172.out | 38 ++++++++++++++++++++++++++++++++++
12
block.c | 148 +++++++++++++++++++++++++++++++++
23
3 files changed, 79 insertions(+), 4 deletions(-)
13
block/block-backend.c | 5 ++
24
14
blockdev.c | 5 ++
25
diff --git a/include/hw/block/block.h b/include/hw/block/block.h
15
6 files changed, 269 insertions(+)
16
17
diff --git a/qapi/block-core.json b/qapi/block-core.json
18
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
19
--- a/qapi/block-core.json
27
--- a/include/hw/block/block.h
20
+++ b/qapi/block-core.json
28
+++ b/include/hw/block/block.h
21
@@ -XXX,XX +XXX,XX @@
29
@@ -XXX,XX +XXX,XX @@
22
##
30
23
{ 'command': 'query-named-block-nodes', 'returns': [ 'BlockDeviceInfo' ] }
31
typedef struct BlockConf {
24
32
BlockBackend *blk;
25
+##
33
+ OnOffAuto backend_defaults;
26
+# @XDbgBlockGraphNodeType:
34
uint32_t physical_block_size;
27
+#
35
uint32_t logical_block_size;
28
+# @block-backend: corresponds to BlockBackend
36
uint32_t min_io_size;
29
+#
37
@@ -XXX,XX +XXX,XX @@ static inline unsigned int get_physical_block_exp(BlockConf *conf)
30
+# @block-job: corresonds to BlockJob
38
}
31
+#
39
32
+# @block-driver: corresponds to BlockDriverState
40
#define DEFINE_BLOCK_PROPERTIES_BASE(_state, _conf) \
33
+#
41
+ DEFINE_PROP_ON_OFF_AUTO("backend_defaults", _state, \
34
+# Since: 4.0
42
+ _conf.backend_defaults, ON_OFF_AUTO_AUTO), \
35
+##
43
DEFINE_PROP_BLOCKSIZE("logical_block_size", _state, \
36
+{ 'enum': 'XDbgBlockGraphNodeType',
44
_conf.logical_block_size), \
37
+ 'data': [ 'block-backend', 'block-job', 'block-driver' ] }
45
DEFINE_PROP_BLOCKSIZE("physical_block_size", _state, \
46
diff --git a/hw/block/block.c b/hw/block/block.c
47
index XXXXXXX..XXXXXXX 100644
48
--- a/hw/block/block.c
49
+++ b/hw/block/block.c
50
@@ -XXX,XX +XXX,XX @@ bool blkconf_blocksizes(BlockConf *conf, Error **errp)
51
{
52
BlockBackend *blk = conf->blk;
53
BlockSizes blocksizes;
54
- int backend_ret;
55
+ BlockDriverState *bs;
56
+ bool use_blocksizes;
57
+ bool use_bs;
38
+
58
+
39
+##
59
+ switch (conf->backend_defaults) {
40
+# @XDbgBlockGraphNode:
60
+ case ON_OFF_AUTO_AUTO:
41
+#
61
+ use_blocksizes = !blk_probe_blocksizes(blk, &blocksizes);
42
+# @id: Block graph node identifier. This @id is generated only for
62
+ use_bs = false;
43
+# x-debug-query-block-graph and does not relate to any other identifiers in
63
+ break;
44
+# Qemu.
45
+#
46
+# @type: Type of graph node. Can be one of block-backend, block-job or
47
+# block-driver-state.
48
+#
49
+# @name: Human readable name of the node. Corresponds to node-name for
50
+# block-driver-state nodes; is not guaranteed to be unique in the whole
51
+# graph (with block-jobs and block-backends).
52
+#
53
+# Since: 4.0
54
+##
55
+{ 'struct': 'XDbgBlockGraphNode',
56
+ 'data': { 'id': 'uint64', 'type': 'XDbgBlockGraphNodeType', 'name': 'str' } }
57
+
64
+
58
+##
65
+ case ON_OFF_AUTO_ON:
59
+# @BlockPermission:
66
+ use_blocksizes = !blk_probe_blocksizes(blk, &blocksizes);
60
+#
67
+ bs = blk_bs(blk);
61
+# Enum of base block permissions.
68
+ use_bs = bs;
62
+#
69
+ break;
63
+# @consistent-read: A user that has the "permission" of consistent reads is
64
+# guaranteed that their view of the contents of the block
65
+# device is complete and self-consistent, representing the
66
+# contents of a disk at a specific point.
67
+# For most block devices (including their backing files) this
68
+# is true, but the property cannot be maintained in a few
69
+# situations like for intermediate nodes of a commit block
70
+# job.
71
+#
72
+# @write: This permission is required to change the visible disk contents.
73
+#
74
+# @write-unchanged: This permission (which is weaker than BLK_PERM_WRITE) is
75
+# both enough and required for writes to the block node when
76
+# the caller promises that the visible disk content doesn't
77
+# change.
78
+# As the BLK_PERM_WRITE permission is strictly stronger,
79
+# either is sufficient to perform an unchanging write.
80
+#
81
+# @resize: This permission is required to change the size of a block node.
82
+#
83
+# @graph-mod: This permission is required to change the node that this
84
+# BdrvChild points to.
85
+#
86
+# Since: 4.0
87
+##
88
+ { 'enum': 'BlockPermission',
89
+ 'data': [ 'consistent-read', 'write', 'write-unchanged', 'resize',
90
+ 'graph-mod' ] }
91
+##
92
+# @XDbgBlockGraphEdge:
93
+#
94
+# Block Graph edge description for x-debug-query-block-graph.
95
+#
96
+# @parent: parent id
97
+#
98
+# @child: child id
99
+#
100
+# @name: name of the relation (examples are 'file' and 'backing')
101
+#
102
+# @perm: granted permissions for the parent operating on the child
103
+#
104
+# @shared-perm: permissions that can still be granted to other users of the
105
+# child while it is still attached to this parent
106
+#
107
+# Since: 4.0
108
+##
109
+{ 'struct': 'XDbgBlockGraphEdge',
110
+ 'data': { 'parent': 'uint64', 'child': 'uint64',
111
+ 'name': 'str', 'perm': [ 'BlockPermission' ],
112
+ 'shared-perm': [ 'BlockPermission' ] } }
113
+
70
+
114
+##
71
+ case ON_OFF_AUTO_OFF:
115
+# @XDbgBlockGraph:
72
+ use_blocksizes = false;
116
+#
73
+ use_bs = false;
117
+# Block Graph - list of nodes and list of edges.
74
+ break;
118
+#
119
+# Since: 4.0
120
+##
121
+{ 'struct': 'XDbgBlockGraph',
122
+ 'data': { 'nodes': ['XDbgBlockGraphNode'], 'edges': ['XDbgBlockGraphEdge'] } }
123
+
75
+
124
+##
76
+ default:
125
+# @x-debug-query-block-graph:
77
+ abort();
126
+#
127
+# Get the block graph.
128
+#
129
+# Since: 4.0
130
+##
131
+{ 'command': 'x-debug-query-block-graph', 'returns': 'XDbgBlockGraph' }
132
+
133
##
134
# @drive-mirror:
135
#
136
diff --git a/include/block/block.h b/include/block/block.h
137
index XXXXXXX..XXXXXXX 100644
138
--- a/include/block/block.h
139
+++ b/include/block/block.h
140
@@ -XXX,XX +XXX,XX @@ void bdrv_eject(BlockDriverState *bs, bool eject_flag);
141
const char *bdrv_get_format_name(BlockDriverState *bs);
142
BlockDriverState *bdrv_find_node(const char *node_name);
143
BlockDeviceInfoList *bdrv_named_nodes_list(Error **errp);
144
+XDbgBlockGraph *bdrv_get_xdbg_block_graph(Error **errp);
145
BlockDriverState *bdrv_lookup_bs(const char *device,
146
const char *node_name,
147
Error **errp);
148
diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h
149
index XXXXXXX..XXXXXXX 100644
150
--- a/include/sysemu/block-backend.h
151
+++ b/include/sysemu/block-backend.h
152
@@ -XXX,XX +XXX,XX @@ int coroutine_fn blk_co_copy_range(BlockBackend *blk_in, int64_t off_in,
153
int bytes, BdrvRequestFlags read_flags,
154
BdrvRequestFlags write_flags);
155
156
+const BdrvChild *blk_root(BlockBackend *blk);
157
+
158
#endif
159
diff --git a/block.c b/block.c
160
index XXXXXXX..XXXXXXX 100644
161
--- a/block.c
162
+++ b/block.c
163
@@ -XXX,XX +XXX,XX @@ BlockDeviceInfoList *bdrv_named_nodes_list(Error **errp)
164
return list;
165
}
166
167
+#define QAPI_LIST_ADD(list, element) do { \
168
+ typeof(list) _tmp = g_new(typeof(*(list)), 1); \
169
+ _tmp->value = (element); \
170
+ _tmp->next = (list); \
171
+ (list) = _tmp; \
172
+} while (0)
173
+
174
+typedef struct XDbgBlockGraphConstructor {
175
+ XDbgBlockGraph *graph;
176
+ GHashTable *graph_nodes;
177
+} XDbgBlockGraphConstructor;
178
+
179
+static XDbgBlockGraphConstructor *xdbg_graph_new(void)
180
+{
181
+ XDbgBlockGraphConstructor *gr = g_new(XDbgBlockGraphConstructor, 1);
182
+
183
+ gr->graph = g_new0(XDbgBlockGraph, 1);
184
+ gr->graph_nodes = g_hash_table_new(NULL, NULL);
185
+
186
+ return gr;
187
+}
188
+
189
+static XDbgBlockGraph *xdbg_graph_finalize(XDbgBlockGraphConstructor *gr)
190
+{
191
+ XDbgBlockGraph *graph = gr->graph;
192
+
193
+ g_hash_table_destroy(gr->graph_nodes);
194
+ g_free(gr);
195
+
196
+ return graph;
197
+}
198
+
199
+static uintptr_t xdbg_graph_node_num(XDbgBlockGraphConstructor *gr, void *node)
200
+{
201
+ uintptr_t ret = (uintptr_t)g_hash_table_lookup(gr->graph_nodes, node);
202
+
203
+ if (ret != 0) {
204
+ return ret;
205
+ }
78
+ }
206
+
79
207
+ /*
80
- backend_ret = blk_probe_blocksizes(blk, &blocksizes);
208
+ * Start counting from 1, not 0, because 0 interferes with not-found (NULL)
81
/* fill in detected values if they are not defined via qemu command line */
209
+ * answer of g_hash_table_lookup.
82
if (!conf->physical_block_size) {
210
+ */
83
- if (!backend_ret) {
211
+ ret = g_hash_table_size(gr->graph_nodes) + 1;
84
+ if (use_blocksizes) {
212
+ g_hash_table_insert(gr->graph_nodes, node, (void *)ret);
85
conf->physical_block_size = blocksizes.phys;
213
+
86
} else {
214
+ return ret;
87
conf->physical_block_size = BDRV_SECTOR_SIZE;
215
+}
88
}
216
+
89
}
217
+static void xdbg_graph_add_node(XDbgBlockGraphConstructor *gr, void *node,
90
if (!conf->logical_block_size) {
218
+ XDbgBlockGraphNodeType type, const char *name)
91
- if (!backend_ret) {
219
+{
92
+ if (use_blocksizes) {
220
+ XDbgBlockGraphNode *n;
93
conf->logical_block_size = blocksizes.log;
221
+
94
} else {
222
+ n = g_new0(XDbgBlockGraphNode, 1);
95
conf->logical_block_size = BDRV_SECTOR_SIZE;
223
+
96
}
224
+ n->id = xdbg_graph_node_num(gr, node);
97
}
225
+ n->type = type;
98
+ if (use_bs) {
226
+ n->name = g_strdup(name);
99
+ if (!conf->opt_io_size) {
227
+
100
+ conf->opt_io_size = bs->bl.opt_transfer;
228
+ QAPI_LIST_ADD(gr->graph->nodes, n);
229
+}
230
+
231
+static void xdbg_graph_add_edge(XDbgBlockGraphConstructor *gr, void *parent,
232
+ const BdrvChild *child)
233
+{
234
+ typedef struct {
235
+ unsigned int flag;
236
+ BlockPermission num;
237
+ } PermissionMap;
238
+
239
+ static const PermissionMap permissions[] = {
240
+ { BLK_PERM_CONSISTENT_READ, BLOCK_PERMISSION_CONSISTENT_READ },
241
+ { BLK_PERM_WRITE, BLOCK_PERMISSION_WRITE },
242
+ { BLK_PERM_WRITE_UNCHANGED, BLOCK_PERMISSION_WRITE_UNCHANGED },
243
+ { BLK_PERM_RESIZE, BLOCK_PERMISSION_RESIZE },
244
+ { BLK_PERM_GRAPH_MOD, BLOCK_PERMISSION_GRAPH_MOD },
245
+ { 0, 0 }
246
+ };
247
+ const PermissionMap *p;
248
+ XDbgBlockGraphEdge *edge;
249
+
250
+ QEMU_BUILD_BUG_ON(1UL << (ARRAY_SIZE(permissions) - 1) != BLK_PERM_ALL + 1);
251
+
252
+ edge = g_new0(XDbgBlockGraphEdge, 1);
253
+
254
+ edge->parent = xdbg_graph_node_num(gr, parent);
255
+ edge->child = xdbg_graph_node_num(gr, child->bs);
256
+ edge->name = g_strdup(child->name);
257
+
258
+ for (p = permissions; p->flag; p++) {
259
+ if (p->flag & child->perm) {
260
+ QAPI_LIST_ADD(edge->perm, p->num);
261
+ }
101
+ }
262
+ if (p->flag & child->shared_perm) {
102
+ if (conf->discard_granularity == -1) {
263
+ QAPI_LIST_ADD(edge->shared_perm, p->num);
103
+ if (bs->bl.pdiscard_alignment) {
104
+ conf->discard_granularity = bs->bl.pdiscard_alignment;
105
+ } else if (bs->bl.request_alignment != 1) {
106
+ conf->discard_granularity = bs->bl.request_alignment;
107
+ }
264
+ }
108
+ }
265
+ }
109
+ }
266
+
110
267
+ QAPI_LIST_ADD(gr->graph->edges, edge);
111
if (conf->logical_block_size > conf->physical_block_size) {
268
+}
112
error_setg(errp,
269
+
113
diff --git a/tests/qemu-iotests/172.out b/tests/qemu-iotests/172.out
270
+
271
+XDbgBlockGraph *bdrv_get_xdbg_block_graph(Error **errp)
272
+{
273
+ BlockBackend *blk;
274
+ BlockJob *job;
275
+ BlockDriverState *bs;
276
+ BdrvChild *child;
277
+ XDbgBlockGraphConstructor *gr = xdbg_graph_new();
278
+
279
+ for (blk = blk_all_next(NULL); blk; blk = blk_all_next(blk)) {
280
+ char *allocated_name = NULL;
281
+ const char *name = blk_name(blk);
282
+
283
+ if (!*name) {
284
+ name = allocated_name = blk_get_attached_dev_id(blk);
285
+ }
286
+ xdbg_graph_add_node(gr, blk, X_DBG_BLOCK_GRAPH_NODE_TYPE_BLOCK_BACKEND,
287
+ name);
288
+ g_free(allocated_name);
289
+ if (blk_root(blk)) {
290
+ xdbg_graph_add_edge(gr, blk, blk_root(blk));
291
+ }
292
+ }
293
+
294
+ for (job = block_job_next(NULL); job; job = block_job_next(job)) {
295
+ GSList *el;
296
+
297
+ xdbg_graph_add_node(gr, job, X_DBG_BLOCK_GRAPH_NODE_TYPE_BLOCK_JOB,
298
+ job->job.id);
299
+ for (el = job->nodes; el; el = el->next) {
300
+ xdbg_graph_add_edge(gr, job, (BdrvChild *)el->data);
301
+ }
302
+ }
303
+
304
+ QTAILQ_FOREACH(bs, &graph_bdrv_states, node_list) {
305
+ xdbg_graph_add_node(gr, bs, X_DBG_BLOCK_GRAPH_NODE_TYPE_BLOCK_DRIVER,
306
+ bs->node_name);
307
+ QLIST_FOREACH(child, &bs->children, next) {
308
+ xdbg_graph_add_edge(gr, bs, child);
309
+ }
310
+ }
311
+
312
+ return xdbg_graph_finalize(gr);
313
+}
314
+
315
BlockDriverState *bdrv_lookup_bs(const char *device,
316
const char *node_name,
317
Error **errp)
318
diff --git a/block/block-backend.c b/block/block-backend.c
319
index XXXXXXX..XXXXXXX 100644
114
index XXXXXXX..XXXXXXX 100644
320
--- a/block/block-backend.c
115
--- a/tests/qemu-iotests/172.out
321
+++ b/block/block-backend.c
116
+++ b/tests/qemu-iotests/172.out
322
@@ -XXX,XX +XXX,XX @@ int coroutine_fn blk_co_copy_range(BlockBackend *blk_in, int64_t off_in,
117
@@ -XXX,XX +XXX,XX @@ Testing:
323
blk_out->root, off_out,
118
dev: floppy, id ""
324
bytes, read_flags, write_flags);
119
unit = 0 (0x0)
325
}
120
drive = "floppy0"
326
+
121
+ backend_defaults = "auto"
327
+const BdrvChild *blk_root(BlockBackend *blk)
122
logical_block_size = 512 (512 B)
328
+{
123
physical_block_size = 512 (512 B)
329
+ return blk->root;
124
min_io_size = 0 (0 B)
330
+}
125
@@ -XXX,XX +XXX,XX @@ Testing: -fda TEST_DIR/t.qcow2
331
diff --git a/blockdev.c b/blockdev.c
126
dev: floppy, id ""
332
index XXXXXXX..XXXXXXX 100644
127
unit = 0 (0x0)
333
--- a/blockdev.c
128
drive = "floppy0"
334
+++ b/blockdev.c
129
+ backend_defaults = "auto"
335
@@ -XXX,XX +XXX,XX @@ BlockDeviceInfoList *qmp_query_named_block_nodes(Error **errp)
130
logical_block_size = 512 (512 B)
336
return bdrv_named_nodes_list(errp);
131
physical_block_size = 512 (512 B)
337
}
132
min_io_size = 0 (0 B)
338
133
@@ -XXX,XX +XXX,XX @@ Testing: -fdb TEST_DIR/t.qcow2
339
+XDbgBlockGraph *qmp_x_debug_query_block_graph(Error **errp)
134
dev: floppy, id ""
340
+{
135
unit = 1 (0x1)
341
+ return bdrv_get_xdbg_block_graph(errp);
136
drive = "floppy1"
342
+}
137
+ backend_defaults = "auto"
343
+
138
logical_block_size = 512 (512 B)
344
BlockJob *do_blockdev_backup(BlockdevBackup *backup, JobTxn *txn,
139
physical_block_size = 512 (512 B)
345
Error **errp)
140
min_io_size = 0 (0 B)
346
{
141
@@ -XXX,XX +XXX,XX @@ Testing: -fdb TEST_DIR/t.qcow2
142
dev: floppy, id ""
143
unit = 0 (0x0)
144
drive = "floppy0"
145
+ backend_defaults = "auto"
146
logical_block_size = 512 (512 B)
147
physical_block_size = 512 (512 B)
148
min_io_size = 0 (0 B)
149
@@ -XXX,XX +XXX,XX @@ Testing: -fda TEST_DIR/t.qcow2 -fdb TEST_DIR/t.qcow2.2
150
dev: floppy, id ""
151
unit = 1 (0x1)
152
drive = "floppy1"
153
+ backend_defaults = "auto"
154
logical_block_size = 512 (512 B)
155
physical_block_size = 512 (512 B)
156
min_io_size = 0 (0 B)
157
@@ -XXX,XX +XXX,XX @@ Testing: -fda TEST_DIR/t.qcow2 -fdb TEST_DIR/t.qcow2.2
158
dev: floppy, id ""
159
unit = 0 (0x0)
160
drive = "floppy0"
161
+ backend_defaults = "auto"
162
logical_block_size = 512 (512 B)
163
physical_block_size = 512 (512 B)
164
min_io_size = 0 (0 B)
165
@@ -XXX,XX +XXX,XX @@ Testing: -fdb
166
dev: floppy, id ""
167
unit = 1 (0x1)
168
drive = "floppy1"
169
+ backend_defaults = "auto"
170
logical_block_size = 512 (512 B)
171
physical_block_size = 512 (512 B)
172
min_io_size = 0 (0 B)
173
@@ -XXX,XX +XXX,XX @@ Testing: -fdb
174
dev: floppy, id ""
175
unit = 0 (0x0)
176
drive = "floppy0"
177
+ backend_defaults = "auto"
178
logical_block_size = 512 (512 B)
179
physical_block_size = 512 (512 B)
180
min_io_size = 0 (0 B)
181
@@ -XXX,XX +XXX,XX @@ Testing: -drive if=floppy,file=TEST_DIR/t.qcow2
182
dev: floppy, id ""
183
unit = 0 (0x0)
184
drive = "floppy0"
185
+ backend_defaults = "auto"
186
logical_block_size = 512 (512 B)
187
physical_block_size = 512 (512 B)
188
min_io_size = 0 (0 B)
189
@@ -XXX,XX +XXX,XX @@ Testing: -drive if=floppy,file=TEST_DIR/t.qcow2,index=1
190
dev: floppy, id ""
191
unit = 1 (0x1)
192
drive = "floppy1"
193
+ backend_defaults = "auto"
194
logical_block_size = 512 (512 B)
195
physical_block_size = 512 (512 B)
196
min_io_size = 0 (0 B)
197
@@ -XXX,XX +XXX,XX @@ Testing: -drive if=floppy,file=TEST_DIR/t.qcow2,index=1
198
dev: floppy, id ""
199
unit = 0 (0x0)
200
drive = "floppy0"
201
+ backend_defaults = "auto"
202
logical_block_size = 512 (512 B)
203
physical_block_size = 512 (512 B)
204
min_io_size = 0 (0 B)
205
@@ -XXX,XX +XXX,XX @@ Testing: -drive if=floppy,file=TEST_DIR/t.qcow2 -drive if=floppy,file=TEST_DIR/t
206
dev: floppy, id ""
207
unit = 1 (0x1)
208
drive = "floppy1"
209
+ backend_defaults = "auto"
210
logical_block_size = 512 (512 B)
211
physical_block_size = 512 (512 B)
212
min_io_size = 0 (0 B)
213
@@ -XXX,XX +XXX,XX @@ Testing: -drive if=floppy,file=TEST_DIR/t.qcow2 -drive if=floppy,file=TEST_DIR/t
214
dev: floppy, id ""
215
unit = 0 (0x0)
216
drive = "floppy0"
217
+ backend_defaults = "auto"
218
logical_block_size = 512 (512 B)
219
physical_block_size = 512 (512 B)
220
min_io_size = 0 (0 B)
221
@@ -XXX,XX +XXX,XX @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -device floppy,drive=none0
222
dev: floppy, id ""
223
unit = 0 (0x0)
224
drive = "none0"
225
+ backend_defaults = "auto"
226
logical_block_size = 512 (512 B)
227
physical_block_size = 512 (512 B)
228
min_io_size = 0 (0 B)
229
@@ -XXX,XX +XXX,XX @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -device floppy,drive=none0,unit=1
230
dev: floppy, id ""
231
unit = 1 (0x1)
232
drive = "none0"
233
+ backend_defaults = "auto"
234
logical_block_size = 512 (512 B)
235
physical_block_size = 512 (512 B)
236
min_io_size = 0 (0 B)
237
@@ -XXX,XX +XXX,XX @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qco
238
dev: floppy, id ""
239
unit = 1 (0x1)
240
drive = "none1"
241
+ backend_defaults = "auto"
242
logical_block_size = 512 (512 B)
243
physical_block_size = 512 (512 B)
244
min_io_size = 0 (0 B)
245
@@ -XXX,XX +XXX,XX @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qco
246
dev: floppy, id ""
247
unit = 0 (0x0)
248
drive = "none0"
249
+ backend_defaults = "auto"
250
logical_block_size = 512 (512 B)
251
physical_block_size = 512 (512 B)
252
min_io_size = 0 (0 B)
253
@@ -XXX,XX +XXX,XX @@ Testing: -fda TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -device fl
254
dev: floppy, id ""
255
unit = 1 (0x1)
256
drive = "none0"
257
+ backend_defaults = "auto"
258
logical_block_size = 512 (512 B)
259
physical_block_size = 512 (512 B)
260
min_io_size = 0 (0 B)
261
@@ -XXX,XX +XXX,XX @@ Testing: -fda TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -device fl
262
dev: floppy, id ""
263
unit = 0 (0x0)
264
drive = "floppy0"
265
+ backend_defaults = "auto"
266
logical_block_size = 512 (512 B)
267
physical_block_size = 512 (512 B)
268
min_io_size = 0 (0 B)
269
@@ -XXX,XX +XXX,XX @@ Testing: -fda TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -device fl
270
dev: floppy, id ""
271
unit = 1 (0x1)
272
drive = "none0"
273
+ backend_defaults = "auto"
274
logical_block_size = 512 (512 B)
275
physical_block_size = 512 (512 B)
276
min_io_size = 0 (0 B)
277
@@ -XXX,XX +XXX,XX @@ Testing: -fda TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -device fl
278
dev: floppy, id ""
279
unit = 0 (0x0)
280
drive = "floppy0"
281
+ backend_defaults = "auto"
282
logical_block_size = 512 (512 B)
283
physical_block_size = 512 (512 B)
284
min_io_size = 0 (0 B)
285
@@ -XXX,XX +XXX,XX @@ Testing: -fdb TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -device fl
286
dev: floppy, id ""
287
unit = 0 (0x0)
288
drive = "none0"
289
+ backend_defaults = "auto"
290
logical_block_size = 512 (512 B)
291
physical_block_size = 512 (512 B)
292
min_io_size = 0 (0 B)
293
@@ -XXX,XX +XXX,XX @@ Testing: -fdb TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -device fl
294
dev: floppy, id ""
295
unit = 1 (0x1)
296
drive = "floppy1"
297
+ backend_defaults = "auto"
298
logical_block_size = 512 (512 B)
299
physical_block_size = 512 (512 B)
300
min_io_size = 0 (0 B)
301
@@ -XXX,XX +XXX,XX @@ Testing: -fdb TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -device fl
302
dev: floppy, id ""
303
unit = 0 (0x0)
304
drive = "none0"
305
+ backend_defaults = "auto"
306
logical_block_size = 512 (512 B)
307
physical_block_size = 512 (512 B)
308
min_io_size = 0 (0 B)
309
@@ -XXX,XX +XXX,XX @@ Testing: -fdb TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -device fl
310
dev: floppy, id ""
311
unit = 1 (0x1)
312
drive = "floppy1"
313
+ backend_defaults = "auto"
314
logical_block_size = 512 (512 B)
315
physical_block_size = 512 (512 B)
316
min_io_size = 0 (0 B)
317
@@ -XXX,XX +XXX,XX @@ Testing: -drive if=floppy,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.q
318
dev: floppy, id ""
319
unit = 1 (0x1)
320
drive = "none0"
321
+ backend_defaults = "auto"
322
logical_block_size = 512 (512 B)
323
physical_block_size = 512 (512 B)
324
min_io_size = 0 (0 B)
325
@@ -XXX,XX +XXX,XX @@ Testing: -drive if=floppy,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.q
326
dev: floppy, id ""
327
unit = 0 (0x0)
328
drive = "floppy0"
329
+ backend_defaults = "auto"
330
logical_block_size = 512 (512 B)
331
physical_block_size = 512 (512 B)
332
min_io_size = 0 (0 B)
333
@@ -XXX,XX +XXX,XX @@ Testing: -drive if=floppy,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.q
334
dev: floppy, id ""
335
unit = 1 (0x1)
336
drive = "none0"
337
+ backend_defaults = "auto"
338
logical_block_size = 512 (512 B)
339
physical_block_size = 512 (512 B)
340
min_io_size = 0 (0 B)
341
@@ -XXX,XX +XXX,XX @@ Testing: -drive if=floppy,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.q
342
dev: floppy, id ""
343
unit = 0 (0x0)
344
drive = "floppy0"
345
+ backend_defaults = "auto"
346
logical_block_size = 512 (512 B)
347
physical_block_size = 512 (512 B)
348
min_io_size = 0 (0 B)
349
@@ -XXX,XX +XXX,XX @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -global floppy.drive=none0 -device
350
dev: floppy, id ""
351
unit = 0 (0x0)
352
drive = "none0"
353
+ backend_defaults = "auto"
354
logical_block_size = 512 (512 B)
355
physical_block_size = 512 (512 B)
356
min_io_size = 0 (0 B)
357
@@ -XXX,XX +XXX,XX @@ Testing: -device floppy
358
dev: floppy, id ""
359
unit = 0 (0x0)
360
drive = ""
361
+ backend_defaults = "auto"
362
logical_block_size = 512 (512 B)
363
physical_block_size = 512 (512 B)
364
min_io_size = 0 (0 B)
365
@@ -XXX,XX +XXX,XX @@ Testing: -device floppy,drive-type=120
366
dev: floppy, id ""
367
unit = 0 (0x0)
368
drive = ""
369
+ backend_defaults = "auto"
370
logical_block_size = 512 (512 B)
371
physical_block_size = 512 (512 B)
372
min_io_size = 0 (0 B)
373
@@ -XXX,XX +XXX,XX @@ Testing: -device floppy,drive-type=144
374
dev: floppy, id ""
375
unit = 0 (0x0)
376
drive = ""
377
+ backend_defaults = "auto"
378
logical_block_size = 512 (512 B)
379
physical_block_size = 512 (512 B)
380
min_io_size = 0 (0 B)
381
@@ -XXX,XX +XXX,XX @@ Testing: -device floppy,drive-type=288
382
dev: floppy, id ""
383
unit = 0 (0x0)
384
drive = ""
385
+ backend_defaults = "auto"
386
logical_block_size = 512 (512 B)
387
physical_block_size = 512 (512 B)
388
min_io_size = 0 (0 B)
389
@@ -XXX,XX +XXX,XX @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -device floppy,drive=none0,drive-t
390
dev: floppy, id ""
391
unit = 0 (0x0)
392
drive = "none0"
393
+ backend_defaults = "auto"
394
logical_block_size = 512 (512 B)
395
physical_block_size = 512 (512 B)
396
min_io_size = 0 (0 B)
397
@@ -XXX,XX +XXX,XX @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -device floppy,drive=none0,drive-t
398
dev: floppy, id ""
399
unit = 0 (0x0)
400
drive = "none0"
401
+ backend_defaults = "auto"
402
logical_block_size = 512 (512 B)
403
physical_block_size = 512 (512 B)
404
min_io_size = 0 (0 B)
405
@@ -XXX,XX +XXX,XX @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -device floppy,drive=none0,logical
406
dev: floppy, id ""
407
unit = 0 (0x0)
408
drive = "none0"
409
+ backend_defaults = "auto"
410
logical_block_size = 512 (512 B)
411
physical_block_size = 512 (512 B)
412
min_io_size = 0 (0 B)
413
@@ -XXX,XX +XXX,XX @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -device floppy,drive=none0,physica
414
dev: floppy, id ""
415
unit = 0 (0x0)
416
drive = "none0"
417
+ backend_defaults = "auto"
418
logical_block_size = 512 (512 B)
419
physical_block_size = 512 (512 B)
420
min_io_size = 0 (0 B)
347
--
421
--
348
2.20.1
422
2.31.1
349
423
350
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
Render block nodes graph with help of graphviz. This new function is
4
for debugging, so there is no sense to put it into qemu.py as a method
5
of QEMUMachine. Let's instead put it separately.
6
7
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
8
Acked-by: Eduardo Habkost <ehabkost@redhat.com>
9
Reviewed-by: Max Reitz <mreitz@redhat.com>
10
Message-id: 20181221170909.25584-3-vsementsov@virtuozzo.com
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
---
13
scripts/render_block_graph.py | 120 ++++++++++++++++++++++++++++++++++
14
1 file changed, 120 insertions(+)
15
create mode 100755 scripts/render_block_graph.py
16
17
diff --git a/scripts/render_block_graph.py b/scripts/render_block_graph.py
18
new file mode 100755
19
index XXXXXXX..XXXXXXX
20
--- /dev/null
21
+++ b/scripts/render_block_graph.py
22
@@ -XXX,XX +XXX,XX @@
23
+#!/usr/bin/env python
24
+#
25
+# Render Qemu Block Graph
26
+#
27
+# Copyright (c) 2018 Virtuozzo International GmbH. All rights reserved.
28
+#
29
+# This program is free software; you can redistribute it and/or modify
30
+# it under the terms of the GNU General Public License as published by
31
+# the Free Software Foundation; either version 2 of the License, or
32
+# (at your option) any later version.
33
+#
34
+# This program is distributed in the hope that it will be useful,
35
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
36
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
37
+# GNU General Public License for more details.
38
+#
39
+# You should have received a copy of the GNU General Public License
40
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
41
+#
42
+
43
+import os
44
+import sys
45
+import subprocess
46
+import json
47
+from graphviz import Digraph
48
+from qemu import MonitorResponseError
49
+
50
+
51
+def perm(arr):
52
+ s = 'w' if 'write' in arr else '_'
53
+ s += 'r' if 'consistent-read' in arr else '_'
54
+ s += 'u' if 'write-unchanged' in arr else '_'
55
+ s += 'g' if 'graph-mod' in arr else '_'
56
+ s += 's' if 'resize' in arr else '_'
57
+ return s
58
+
59
+
60
+def render_block_graph(qmp, filename, format='png'):
61
+ '''
62
+ Render graph in text (dot) representation into "@filename" and
63
+ representation in @format into "@filename.@format"
64
+ '''
65
+
66
+ bds_nodes = qmp.command('query-named-block-nodes')
67
+ bds_nodes = {n['node-name']: n for n in bds_nodes}
68
+
69
+ job_nodes = qmp.command('query-block-jobs')
70
+ job_nodes = {n['device']: n for n in job_nodes}
71
+
72
+ block_graph = qmp.command('x-debug-query-block-graph')
73
+
74
+ graph = Digraph(comment='Block Nodes Graph')
75
+ graph.format = format
76
+ graph.node('permission symbols:\l'
77
+ ' w - Write\l'
78
+ ' r - consistent-Read\l'
79
+ ' u - write - Unchanged\l'
80
+ ' g - Graph-mod\l'
81
+ ' s - reSize\l'
82
+ 'edge label scheme:\l'
83
+ ' <child type>\l'
84
+ ' <perm>\l'
85
+ ' <shared_perm>\l', shape='none')
86
+
87
+ for n in block_graph['nodes']:
88
+ if n['type'] == 'block-driver':
89
+ info = bds_nodes[n['name']]
90
+ label = n['name'] + ' [' + info['drv'] + ']'
91
+ if info['drv'] == 'file':
92
+ label += '\n' + os.path.basename(info['file'])
93
+ shape = 'ellipse'
94
+ elif n['type'] == 'block-job':
95
+ info = job_nodes[n['name']]
96
+ label = info['type'] + ' job (' + n['name'] + ')'
97
+ shape = 'box'
98
+ else:
99
+ assert n['type'] == 'block-backend'
100
+ label = n['name'] if n['name'] else 'unnamed blk'
101
+ shape = 'box'
102
+
103
+ graph.node(str(n['id']), label, shape=shape)
104
+
105
+ for e in block_graph['edges']:
106
+ label = '%s\l%s\l%s\l' % (e['name'], perm(e['perm']),
107
+ perm(e['shared-perm']))
108
+ graph.edge(str(e['parent']), str(e['child']), label=label)
109
+
110
+ graph.render(filename)
111
+
112
+
113
+class LibvirtGuest():
114
+ def __init__(self, name):
115
+ self.name = name
116
+
117
+ def command(self, cmd):
118
+ # only supports qmp commands without parameters
119
+ m = {'execute': cmd}
120
+ ar = ['virsh', 'qemu-monitor-command', self.name, json.dumps(m)]
121
+
122
+ reply = json.loads(subprocess.check_output(ar))
123
+
124
+ if 'error' in reply:
125
+ raise MonitorResponseError(reply)
126
+
127
+ return reply['return']
128
+
129
+
130
+if __name__ == '__main__':
131
+ obj = sys.argv[1]
132
+ out = sys.argv[2]
133
+
134
+ if os.path.exists(obj):
135
+ # assume unix socket
136
+ qmp = QEMUMonitorProtocol(obj)
137
+ qmp.connect()
138
+ else:
139
+ # assume libvirt guest name
140
+ qmp = LibvirtGuest(obj)
141
+
142
+ render_block_graph(qmp, out)
143
--
144
2.20.1
145
146
diff view generated by jsdifflib
Deleted patch
1
From: Laurent Vivier <lvivier@redhat.com>
2
1
3
Signed-off-by: Laurent Vivier <lvivier@redhat.com>
4
Reviewed-by: Richard W.M. Jones <rjones@redhat.com>
5
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
6
Message-id: 20181213162727.17438-3-lvivier@redhat.com
7
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
---
9
block/curl.c | 29 ++++++++---------------------
10
block/trace-events | 9 +++++++++
11
2 files changed, 17 insertions(+), 21 deletions(-)
12
13
diff --git a/block/curl.c b/block/curl.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/block/curl.c
16
+++ b/block/curl.c
17
@@ -XXX,XX +XXX,XX @@
18
#include "crypto/secret.h"
19
#include <curl/curl.h>
20
#include "qemu/cutils.h"
21
+#include "trace.h"
22
23
-// #define DEBUG_CURL
24
// #define DEBUG_VERBOSE
25
26
-#ifdef DEBUG_CURL
27
-#define DEBUG_CURL_PRINT 1
28
-#else
29
-#define DEBUG_CURL_PRINT 0
30
-#endif
31
-#define DPRINTF(fmt, ...) \
32
- do { \
33
- if (DEBUG_CURL_PRINT) { \
34
- fprintf(stderr, fmt, ## __VA_ARGS__); \
35
- } \
36
- } while (0)
37
-
38
#if LIBCURL_VERSION_NUM >= 0x071000
39
/* The multi interface timer callback was introduced in 7.16.0 */
40
#define NEED_CURL_TIMER_CALLBACK
41
@@ -XXX,XX +XXX,XX @@ static int curl_timer_cb(CURLM *multi, long timeout_ms, void *opaque)
42
{
43
BDRVCURLState *s = opaque;
44
45
- DPRINTF("CURL: timer callback timeout_ms %ld\n", timeout_ms);
46
+ trace_curl_timer_cb(timeout_ms);
47
if (timeout_ms == -1) {
48
timer_del(&s->timer);
49
} else {
50
@@ -XXX,XX +XXX,XX @@ static int curl_sock_cb(CURL *curl, curl_socket_t fd, int action,
51
}
52
socket = NULL;
53
54
- DPRINTF("CURL (AIO): Sock action %d on fd %d\n", action, (int)fd);
55
+ trace_curl_sock_cb(action, (int)fd);
56
switch (action) {
57
case CURL_POLL_IN:
58
aio_set_fd_handler(s->aio_context, fd, false,
59
@@ -XXX,XX +XXX,XX @@ static size_t curl_read_cb(void *ptr, size_t size, size_t nmemb, void *opaque)
60
size_t realsize = size * nmemb;
61
int i;
62
63
- DPRINTF("CURL: Just reading %zd bytes\n", realsize);
64
+ trace_curl_read_cb(realsize);
65
66
if (!s || !s->orig_buf) {
67
goto read_end;
68
@@ -XXX,XX +XXX,XX @@ static int curl_open(BlockDriverState *bs, QDict *options, int flags,
69
}
70
}
71
72
- DPRINTF("CURL: Opening %s\n", file);
73
+ trace_curl_open(file);
74
qemu_co_queue_init(&s->free_state_waitq);
75
s->aio_context = bdrv_get_aio_context(bs);
76
s->url = g_strdup(file);
77
@@ -XXX,XX +XXX,XX @@ static int curl_open(BlockDriverState *bs, QDict *options, int flags,
78
"Server does not support 'range' (byte ranges).");
79
goto out;
80
}
81
- DPRINTF("CURL: Size = %" PRIu64 "\n", s->len);
82
+ trace_curl_open_size(s->len);
83
84
qemu_mutex_lock(&s->mutex);
85
curl_clean_state(state);
86
@@ -XXX,XX +XXX,XX @@ static void curl_setup_preadv(BlockDriverState *bs, CURLAIOCB *acb)
87
state->acb[0] = acb;
88
89
snprintf(state->range, 127, "%" PRIu64 "-%" PRIu64, start, end);
90
- DPRINTF("CURL (AIO): Reading %" PRIu64 " at %" PRIu64 " (%s)\n",
91
- acb->bytes, start, state->range);
92
+ trace_curl_setup_preadv(acb->bytes, start, state->range);
93
curl_easy_setopt(state->curl, CURLOPT_RANGE, state->range);
94
95
curl_multi_add_handle(s->multi, state->curl);
96
@@ -XXX,XX +XXX,XX @@ static void curl_close(BlockDriverState *bs)
97
{
98
BDRVCURLState *s = bs->opaque;
99
100
- DPRINTF("CURL: Close\n");
101
+ trace_curl_close();
102
curl_detach_aio_context(bs);
103
qemu_mutex_destroy(&s->mutex);
104
105
diff --git a/block/trace-events b/block/trace-events
106
index XXXXXXX..XXXXXXX 100644
107
--- a/block/trace-events
108
+++ b/block/trace-events
109
@@ -XXX,XX +XXX,XX @@ ssh_write(int64_t offset, size_t size) "offset=%" PRIi64 " size=%zu"
110
ssh_write_buf(void *buf, size_t size) "sftp_write buf=%p size=%zu"
111
ssh_write_return(ssize_t ret) "sftp_write returned %zd"
112
ssh_seek(int64_t offset) "seeking to offset=%" PRIi64
113
+
114
+# block/curl.c
115
+curl_timer_cb(long timeout_ms) "timer callback timeout_ms %ld"
116
+curl_sock_cb(int action, int fd) "sock action %d on fd %d"
117
+curl_read_cb(size_t realsize) "just reading %zu bytes"
118
+curl_open(const char *file) "opening %s"
119
+curl_open_size(uint64_t size) "size = %" PRIu64
120
+curl_setup_preadv(uint64_t bytes, uint64_t start, const char *range) "reading %" PRIu64 " at %" PRIu64 " (%s)"
121
+curl_close(void) "close"
122
--
123
2.20.1
124
125
diff view generated by jsdifflib
Deleted patch
1
From: Laurent Vivier <lvivier@redhat.com>
2
1
3
Signed-off-by: Laurent Vivier <lvivier@redhat.com>
4
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
5
Message-id: 20181213162727.17438-5-lvivier@redhat.com
6
[mreitz: Fixed sheepdog_snapshot_create_inode's format string to use
7
PRIx32 for uint32_ts]
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
---
10
block/sheepdog.c | 47 +++++++++++++++++-----------------------------
11
block/trace-events | 14 ++++++++++++++
12
2 files changed, 31 insertions(+), 30 deletions(-)
13
14
diff --git a/block/sheepdog.c b/block/sheepdog.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/block/sheepdog.c
17
+++ b/block/sheepdog.c
18
@@ -XXX,XX +XXX,XX @@
19
#include "sysemu/block-backend.h"
20
#include "qemu/bitops.h"
21
#include "qemu/cutils.h"
22
+#include "trace.h"
23
24
#define SD_PROTO_VER 0x01
25
26
@@ -XXX,XX +XXX,XX @@ static inline size_t count_data_objs(const struct SheepdogInode *inode)
27
(1UL << inode->block_size_shift));
28
}
29
30
-#undef DPRINTF
31
-#ifdef DEBUG_SDOG
32
-#define DEBUG_SDOG_PRINT 1
33
-#else
34
-#define DEBUG_SDOG_PRINT 0
35
-#endif
36
-#define DPRINTF(fmt, args...) \
37
- do { \
38
- if (DEBUG_SDOG_PRINT) { \
39
- fprintf(stderr, "%s %d: " fmt, __func__, __LINE__, ##args); \
40
- } \
41
- } while (0)
42
-
43
typedef struct SheepdogAIOCB SheepdogAIOCB;
44
typedef struct BDRVSheepdogState BDRVSheepdogState;
45
46
@@ -XXX,XX +XXX,XX @@ static coroutine_fn void reconnect_to_sdog(void *opaque)
47
Error *local_err = NULL;
48
s->fd = get_sheep_fd(s, &local_err);
49
if (s->fd < 0) {
50
- DPRINTF("Wait for connection to be established\n");
51
+ trace_sheepdog_reconnect_to_sdog();
52
error_report_err(local_err);
53
qemu_co_sleep_ns(QEMU_CLOCK_REALTIME, 1000000000ULL);
54
}
55
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn aio_read_response(void *opaque)
56
break;
57
case AIOCB_FLUSH_CACHE:
58
if (rsp.result == SD_RES_INVALID_PARMS) {
59
- DPRINTF("disable cache since the server doesn't support it\n");
60
+ trace_sheepdog_aio_read_response();
61
s->cache_flags = SD_FLAG_CMD_DIRECT;
62
rsp.result = SD_RES_SUCCESS;
63
}
64
@@ -XXX,XX +XXX,XX @@ static int sd_open(BlockDriverState *bs, QDict *options, int flags,
65
s->discard_supported = true;
66
67
if (snap_id || tag[0]) {
68
- DPRINTF("%" PRIx32 " snapshot inode was open.\n", vid);
69
+ trace_sheepdog_open(vid);
70
s->is_snapshot = true;
71
}
72
73
@@ -XXX,XX +XXX,XX @@ static void sd_close(BlockDriverState *bs)
74
unsigned int wlen, rlen = 0;
75
int fd, ret;
76
77
- DPRINTF("%s\n", s->name);
78
+ trace_sheepdog_close(s->name);
79
80
fd = connect_to_sdog(s, &local_err);
81
if (fd < 0) {
82
@@ -XXX,XX +XXX,XX @@ static int sd_create_branch(BDRVSheepdogState *s)
83
char *buf;
84
bool deleted;
85
86
- DPRINTF("%" PRIx32 " is snapshot.\n", s->inode.vdi_id);
87
+ trace_sheepdog_create_branch_snapshot(s->inode.vdi_id);
88
89
buf = g_malloc(SD_INODE_SIZE);
90
91
@@ -XXX,XX +XXX,XX @@ static int sd_create_branch(BDRVSheepdogState *s)
92
goto out;
93
}
94
95
- DPRINTF("%" PRIx32 " is created.\n", vid);
96
+ trace_sheepdog_create_branch_created(vid);
97
98
fd = connect_to_sdog(s, &local_err);
99
if (fd < 0) {
100
@@ -XXX,XX +XXX,XX @@ static int sd_create_branch(BDRVSheepdogState *s)
101
102
s->is_snapshot = false;
103
ret = 0;
104
- DPRINTF("%" PRIx32 " was newly created.\n", s->inode.vdi_id);
105
+ trace_sheepdog_create_branch_new(s->inode.vdi_id);
106
107
out:
108
g_free(buf);
109
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn sd_co_rw_vector(SheepdogAIOCB *acb)
110
}
111
112
if (create) {
113
- DPRINTF("update ino (%" PRIu32 ") %" PRIu64 " %" PRIu64 " %ld\n",
114
- inode->vdi_id, oid,
115
- vid_to_data_oid(inode->data_vdi_id[idx], idx), idx);
116
+ trace_sheepdog_co_rw_vector_update(inode->vdi_id, oid,
117
+ vid_to_data_oid(inode->data_vdi_id[idx], idx),
118
+ idx);
119
oid = vid_to_data_oid(inode->vdi_id, idx);
120
- DPRINTF("new oid %" PRIx64 "\n", oid);
121
+ trace_sheepdog_co_rw_vector_new(oid);
122
}
123
124
aio_req = alloc_aio_req(s, acb, oid, len, offset, flags, create,
125
@@ -XXX,XX +XXX,XX @@ static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
126
SheepdogInode *inode;
127
unsigned int datalen;
128
129
- DPRINTF("sn_info: name %s id_str %s s: name %s vm_state_size %" PRId64 " "
130
- "is_snapshot %d\n", sn_info->name, sn_info->id_str,
131
- s->name, sn_info->vm_state_size, s->is_snapshot);
132
+ trace_sheepdog_snapshot_create_info(sn_info->name, sn_info->id_str, s->name,
133
+ sn_info->vm_state_size, s->is_snapshot);
134
135
if (s->is_snapshot) {
136
error_report("You can't create a snapshot of a snapshot VDI, "
137
@@ -XXX,XX +XXX,XX @@ static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
138
return -EINVAL;
139
}
140
141
- DPRINTF("%s %s\n", sn_info->name, sn_info->id_str);
142
+ trace_sheepdog_snapshot_create(sn_info->name, sn_info->id_str);
143
144
s->inode.vm_state_size = sn_info->vm_state_size;
145
s->inode.vm_clock_nsec = sn_info->vm_clock_nsec;
146
@@ -XXX,XX +XXX,XX @@ static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
147
}
148
149
memcpy(&s->inode, inode, datalen);
150
- DPRINTF("s->inode: name %s snap_id %x oid %x\n",
151
- s->inode.name, s->inode.snap_id, s->inode.vdi_id);
152
+ trace_sheepdog_snapshot_create_inode(s->inode.name, s->inode.snap_id,
153
+ s->inode.vdi_id);
154
155
cleanup:
156
g_free(inode);
157
diff --git a/block/trace-events b/block/trace-events
158
index XXXXXXX..XXXXXXX 100644
159
--- a/block/trace-events
160
+++ b/block/trace-events
161
@@ -XXX,XX +XXX,XX @@ file_xfs_discard(const char *error) "cannot punch hole (%s)"
162
file_FindEjectableOpticalMedia(const char *media) "Matching using %s"
163
file_setup_cdrom(const char *partition) "Using %s as optical disc"
164
file_hdev_is_sg(int type, int version) "SG device found: type=%d, version=%d"
165
+
166
+# block/sheepdog.c
167
+sheepdog_reconnect_to_sdog(void) "Wait for connection to be established"
168
+sheepdog_aio_read_response(void) "disable cache since the server doesn't support it"
169
+sheepdog_open(uint32_t vid) "0x%" PRIx32 " snapshot inode was open"
170
+sheepdog_close(const char *name) "%s"
171
+sheepdog_create_branch_snapshot(uint32_t vdi) "0x%" PRIx32 " is snapshot"
172
+sheepdog_create_branch_created(uint32_t vdi) "0x%" PRIx32 " is created"
173
+sheepdog_create_branch_new(uint32_t vdi) "0x%" PRIx32 " was newly created"
174
+sheepdog_co_rw_vector_update(uint32_t vdi, uint64_t oid, uint64_t data, long idx) "update ino (%" PRIu32 ") %" PRIu64 " %" PRIu64 " %ld"
175
+sheepdog_co_rw_vector_new(uint64_t oid) "new oid 0x%" PRIx64
176
+sheepdog_snapshot_create_info(const char *sn_name, const char *id, const char *name, int64_t size, int is_snapshot) "sn_info: name %s id_str %s s: name %s vm_state_size %" PRId64 " " "is_snapshot %d"
177
+sheepdog_snapshot_create(const char *sn_name, const char *id) "%s %s"
178
+sheepdog_snapshot_create_inode(const char *name, uint32_t snap, uint32_t vdi) "s->inode: name %s snap_id 0x%" PRIx32 " vdi 0x%" PRIx32
179
--
180
2.20.1
181
182
diff view generated by jsdifflib
Deleted patch
1
From: "Richard W.M. Jones" <rjones@redhat.com>
2
1
3
On FreeBSD 11.2:
4
5
$ nbdkit memory size=1M --run './qemu-io -f raw -c "aio_write 0 512" $nbd'
6
Parsing error: non-numeric argument, or extraneous/unrecognized suffix -- aio_write
7
8
After main option parsing, we reinitialize optind so we can parse each
9
command. However reinitializing optind to 0 does not work on FreeBSD.
10
What happens when you do this is optind remains 0 after the option
11
parsing loop, and the result is we try to parse argv[optind] ==
12
argv[0] == "aio_write" as if it was the first parameter.
13
14
The FreeBSD manual page says:
15
16
In order to use getopt() to evaluate multiple sets of arguments, or to
17
evaluate a single set of arguments multiple times, the variable optreset
18
must be set to 1 before the second and each additional set of calls to
19
getopt(), and the variable optind must be reinitialized.
20
21
(From the rest of the man page it is clear that optind must be
22
reinitialized to 1).
23
24
The glibc man page says:
25
26
A program that scans multiple argument vectors, or rescans the same
27
vector more than once, and wants to make use of GNU extensions such as
28
'+' and '-' at the start of optstring, or changes the value of
29
POSIXLY_CORRECT between scans, must reinitialize getopt() by resetting
30
optind to 0, rather than the traditional value of 1. (Resetting to 0
31
forces the invocation of an internal initialization routine that
32
rechecks POSIXLY_CORRECT and checks for GNU extensions in optstring.)
33
34
This commit introduces an OS-portability function called
35
qemu_reset_optind which provides a way of resetting optind that works
36
on FreeBSD and platforms that use optreset, while keeping it the same
37
as now on other platforms.
38
39
Note that the qemu codebase sets optind in many other places, but in
40
those other places it's setting a local variable and not using getopt.
41
This change is only needed in places where we are using getopt and the
42
associated global variable optind.
43
44
Signed-off-by: Richard W.M. Jones <rjones@redhat.com>
45
Message-id: 20190118101114.11759-2-rjones@redhat.com
46
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
47
Reviewed-by: Eric Blake <eblake@redhat.com>
48
Signed-off-by: Max Reitz <mreitz@redhat.com>
49
---
50
configure | 14 ++++++++++++++
51
include/qemu/osdep.h | 16 ++++++++++++++++
52
qemu-img.c | 2 +-
53
qemu-io-cmds.c | 2 +-
54
4 files changed, 32 insertions(+), 2 deletions(-)
55
56
diff --git a/configure b/configure
57
index XXXXXXX..XXXXXXX 100755
58
--- a/configure
59
+++ b/configure
60
@@ -XXX,XX +XXX,XX @@ if compile_prog "" "" ; then
61
signalfd=yes
62
fi
63
64
+# check if optreset global is declared by <getopt.h>
65
+optreset="no"
66
+cat > $TMPC << EOF
67
+#include <getopt.h>
68
+int main(void) { return optreset; }
69
+EOF
70
+
71
+if compile_prog "" "" ; then
72
+ optreset=yes
73
+fi
74
+
75
# check if eventfd is supported
76
eventfd=no
77
cat > $TMPC << EOF
78
@@ -XXX,XX +XXX,XX @@ fi
79
if test "$signalfd" = "yes" ; then
80
echo "CONFIG_SIGNALFD=y" >> $config_host_mak
81
fi
82
+if test "$optreset" = "yes" ; then
83
+ echo "HAVE_OPTRESET=y" >> $config_host_mak
84
+fi
85
if test "$tcg" = "yes"; then
86
echo "CONFIG_TCG=y" >> $config_host_mak
87
if test "$tcg_interpreter" = "yes" ; then
88
diff --git a/include/qemu/osdep.h b/include/qemu/osdep.h
89
index XXXXXXX..XXXXXXX 100644
90
--- a/include/qemu/osdep.h
91
+++ b/include/qemu/osdep.h
92
@@ -XXX,XX +XXX,XX @@ extern int daemon(int, int);
93
#include <ctype.h>
94
#include <errno.h>
95
#include <fcntl.h>
96
+#include <getopt.h>
97
#include <sys/stat.h>
98
#include <sys/time.h>
99
#include <assert.h>
100
@@ -XXX,XX +XXX,XX @@ extern int qemu_icache_linesize_log;
101
extern int qemu_dcache_linesize;
102
extern int qemu_dcache_linesize_log;
103
104
+/*
105
+ * After using getopt or getopt_long, if you need to parse another set
106
+ * of options, then you must reset optind. Unfortunately the way to
107
+ * do this varies between implementations of getopt.
108
+ */
109
+static inline void qemu_reset_optind(void)
110
+{
111
+#ifdef HAVE_OPTRESET
112
+ optind = 1;
113
+ optreset = 1;
114
+#else
115
+ optind = 0;
116
+#endif
117
+}
118
+
119
#endif
120
diff --git a/qemu-img.c b/qemu-img.c
121
index XXXXXXX..XXXXXXX 100644
122
--- a/qemu-img.c
123
+++ b/qemu-img.c
124
@@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv)
125
return 0;
126
}
127
argv += optind;
128
- optind = 0;
129
+ qemu_reset_optind();
130
131
if (!trace_init_backends()) {
132
exit(1);
133
diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
134
index XXXXXXX..XXXXXXX 100644
135
--- a/qemu-io-cmds.c
136
+++ b/qemu-io-cmds.c
137
@@ -XXX,XX +XXX,XX @@ static int command(BlockBackend *blk, const cmdinfo_t *ct, int argc,
138
}
139
}
140
141
- optind = 0;
142
+ qemu_reset_optind();
143
return ct->cfunc(blk, argc, argv);
144
}
145
146
--
147
2.20.1
148
149
diff view generated by jsdifflib
Deleted patch
1
From: Li Qiang <liq3ea@163.com>
2
1
3
Signed-off-by: Li Qiang <liq3ea@163.com>
4
Reviewed-by: Max Reitz <mreitz@redhat.com>
5
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
6
Message-id: 20190120055558.32984-2-liq3ea@163.com
7
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
---
9
hw/block/nvme.c | 2 +-
10
1 file changed, 1 insertion(+), 1 deletion(-)
11
12
diff --git a/hw/block/nvme.c b/hw/block/nvme.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/block/nvme.c
15
+++ b/hw/block/nvme.c
16
@@ -XXX,XX +XXX,XX @@ static void nvme_instance_init(Object *obj)
17
}
18
19
static const TypeInfo nvme_info = {
20
- .name = "nvme",
21
+ .name = TYPE_NVME,
22
.parent = TYPE_PCI_DEVICE,
23
.instance_size = sizeof(NvmeCtrl),
24
.class_init = nvme_class_init,
25
--
26
2.20.1
27
28
diff view generated by jsdifflib
Deleted patch
1
From: Li Qiang <liq3ea@163.com>
2
1
3
When it is zero, it causes segv.
4
Using following command:
5
6
"-drive file=//home/test/test1.img,if=none,id=id0
7
-device nvme,drive=id0,serial=test,num_queues=0"
8
causes following Backtrack:
9
10
Thread 4 "qemu-system-x86" received signal SIGSEGV, Segmentation fault.
11
[Switching to Thread 0x7fffe9735700 (LWP 30952)]
12
0x0000555555a7a77c in nvme_start_ctrl (n=0x5555577473f0) at hw/block/nvme.c:825
13
825     if (unlikely(n->cq[0])) {
14
(gdb) bt
15
0 0x0000555555a7a77c in nvme_start_ctrl (n=0x5555577473f0)
16
at hw/block/nvme.c:825
17
1 0x0000555555a7af7f in nvme_write_bar (n=0x5555577473f0, offset=20,
18
data=4587521, size=4) at hw/block/nvme.c:969
19
2 0x0000555555a7b81a in nvme_mmio_write (opaque=0x5555577473f0, addr=20,
20
data=4587521, size=4) at hw/block/nvme.c:1163
21
3 0x0000555555869236 in memory_region_write_accessor (mr=0x555557747cd0,
22
addr=20, value=0x7fffe97320f8, size=4, shift=0, mask=4294967295, attrs=...)
23
at /home/test/qemu1/qemu/memory.c:502
24
4 0x0000555555869446 in access_with_adjusted_size (addr=20,
25
value=0x7fffe97320f8, size=4, access_size_min=2, access_size_max=8,
26
access_fn=0x55555586914d <memory_region_write_accessor>,
27
mr=0x555557747cd0, attrs=...) at /home/test/qemu1/qemu/memory.c:568
28
5 0x000055555586c479 in memory_region_dispatch_write (mr=0x555557747cd0,
29
addr=20, data=4587521, size=4, attrs=...)
30
at /home/test/qemu1/qemu/memory.c:1499
31
6 0x00005555558030af in flatview_write_continue (fv=0x7fffe0061130,
32
addr=4273930260, attrs=..., buf=0x7ffff7ff0028 "\001", len=4, addr1=20,
33
l=4, mr=0x555557747cd0) at /home/test/qemu1/qemu/exec.c:3234
34
7 0x00005555558031f9 in flatview_write (fv=0x7fffe0061130, addr=4273930260,
35
attrs=..., buf=0x7ffff7ff0028 "\001", len=4)
36
at /home/test/qemu1/qemu/exec.c:3273
37
8 0x00005555558034ff in address_space_write (
38
---Type <return> to continue, or q <return> to quit---
39
as=0x555556758480 <address_space_memory>, addr=4273930260, attrs=...,
40
buf=0x7ffff7ff0028 "\001", len=4) at /home/test/qemu1/qemu/exec.c:3363
41
9 0x0000555555803550 in address_space_rw (
42
as=0x555556758480 <address_space_memory>, addr=4273930260, attrs=...,
43
buf=0x7ffff7ff0028 "\001", len=4, is_write=true)
44
at /home/test/qemu1/qemu/exec.c:3374
45
10 0x00005555558884a1 in kvm_cpu_exec (cpu=0x555556920e40)
46
at /home/test/qemu1/qemu/accel/kvm/kvm-all.c:2031
47
11 0x000055555584cd9d in qemu_kvm_cpu_thread_fn (arg=0x555556920e40)
48
at /home/test/qemu1/qemu/cpus.c:1281
49
12 0x0000555555dbaf6d in qemu_thread_start (args=0x5555569438a0)
50
at util/qemu-thread-posix.c:502
51
13 0x00007ffff5dc86db in start_thread (arg=0x7fffe9735700)
52
at pthread_create.c:463
53
14 0x00007ffff5af188f in clone ()
54
at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95
55
56
Signed-off-by: Li Qiang <liq3ea@163.com>
57
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
58
Message-id: 20190120055558.32984-3-liq3ea@163.com
59
Signed-off-by: Max Reitz <mreitz@redhat.com>
60
---
61
hw/block/nvme.c | 5 +++++
62
1 file changed, 5 insertions(+)
63
64
diff --git a/hw/block/nvme.c b/hw/block/nvme.c
65
index XXXXXXX..XXXXXXX 100644
66
--- a/hw/block/nvme.c
67
+++ b/hw/block/nvme.c
68
@@ -XXX,XX +XXX,XX @@ static void nvme_realize(PCIDevice *pci_dev, Error **errp)
69
int64_t bs_size;
70
uint8_t *pci_conf;
71
72
+ if (!n->num_queues) {
73
+ error_setg(errp, "num_queues can't be zero");
74
+ return;
75
+ }
76
+
77
if (!n->conf.blk) {
78
error_setg(errp, "drive property not set");
79
return;
80
--
81
2.20.1
82
83
diff view generated by jsdifflib
Deleted patch
1
From: Li Qiang <liq3ea@163.com>
2
1
3
There is no need to make another reference.
4
5
Signed-off-by: Li Qiang <liq3ea@163.com>
6
Reviewed-by: Max Reitz <mreitz@redhat.com>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
8
Message-id: 20190120055558.32984-4-liq3ea@163.com
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
---
11
hw/block/nvme.c | 8 ++++----
12
1 file changed, 4 insertions(+), 4 deletions(-)
13
14
diff --git a/hw/block/nvme.c b/hw/block/nvme.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/block/nvme.c
17
+++ b/hw/block/nvme.c
18
@@ -XXX,XX +XXX,XX @@ static void nvme_realize(PCIDevice *pci_dev, Error **errp)
19
pci_conf[PCI_INTERRUPT_PIN] = 1;
20
pci_config_set_prog_interface(pci_dev->config, 0x2);
21
pci_config_set_class(pci_dev->config, PCI_CLASS_STORAGE_EXPRESS);
22
- pcie_endpoint_cap_init(&n->parent_obj, 0x80);
23
+ pcie_endpoint_cap_init(pci_dev, 0x80);
24
25
n->num_namespaces = 1;
26
n->reg_size = pow2ceil(0x1004 + 2 * (n->num_queues + 1) * 4);
27
@@ -XXX,XX +XXX,XX @@ static void nvme_realize(PCIDevice *pci_dev, Error **errp)
28
29
memory_region_init_io(&n->iomem, OBJECT(n), &nvme_mmio_ops, n,
30
"nvme", n->reg_size);
31
- pci_register_bar(&n->parent_obj, 0,
32
+ pci_register_bar(pci_dev, 0,
33
PCI_BASE_ADDRESS_SPACE_MEMORY | PCI_BASE_ADDRESS_MEM_TYPE_64,
34
&n->iomem);
35
- msix_init_exclusive_bar(&n->parent_obj, n->num_queues, 4, NULL);
36
+ msix_init_exclusive_bar(pci_dev, n->num_queues, 4, NULL);
37
38
id->vid = cpu_to_le16(pci_get_word(pci_conf + PCI_VENDOR_ID));
39
id->ssvid = cpu_to_le16(pci_get_word(pci_conf + PCI_SUBSYSTEM_VENDOR_ID));
40
@@ -XXX,XX +XXX,XX @@ static void nvme_realize(PCIDevice *pci_dev, Error **errp)
41
n->cmbuf = g_malloc0(NVME_CMBSZ_GETSIZE(n->bar.cmbsz));
42
memory_region_init_io(&n->ctrl_mem, OBJECT(n), &nvme_cmb_ops, n,
43
"nvme-cmb", NVME_CMBSZ_GETSIZE(n->bar.cmbsz));
44
- pci_register_bar(&n->parent_obj, NVME_CMBLOC_BIR(n->bar.cmbloc),
45
+ pci_register_bar(pci_dev, NVME_CMBLOC_BIR(n->bar.cmbloc),
46
PCI_BASE_ADDRESS_SPACE_MEMORY | PCI_BASE_ADDRESS_MEM_TYPE_64 |
47
PCI_BASE_ADDRESS_MEM_PREFETCH, &n->ctrl_mem);
48
49
--
50
2.20.1
51
52
diff view generated by jsdifflib
Deleted patch
1
In some cases, we may want to deal with qemu-nbd errors (e.g. by
2
launching it in a different configuration until it no longer throws
3
any). In that case, we do not want its output ending up in the test
4
output.
5
1
6
It may still be useful for handling the error, though, so add a new
7
function that works basically like qemu_nbd(), only that it returns the
8
qemu-nbd output instead of making it end up in the log. In contrast to
9
qemu_img_pipe(), it does still return the exit code as well, though,
10
because that is even more important for error handling.
11
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
13
Message-id: 20181221234750.23577-2-mreitz@redhat.com
14
Reviewed-by: John Snow <jsnow@redhat.com>
15
Reviewed-by: Eric Blake <eblake@redhat.com>
16
Signed-off-by: Max Reitz <mreitz@redhat.com>
17
---
18
tests/qemu-iotests/iotests.py | 14 ++++++++++++++
19
1 file changed, 14 insertions(+)
20
21
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
22
index XXXXXXX..XXXXXXX 100644
23
--- a/tests/qemu-iotests/iotests.py
24
+++ b/tests/qemu-iotests/iotests.py
25
@@ -XXX,XX +XXX,XX @@ def qemu_nbd(*args):
26
'''Run qemu-nbd in daemon mode and return the parent's exit code'''
27
return subprocess.call(qemu_nbd_args + ['--fork'] + list(args))
28
29
+def qemu_nbd_pipe(*args):
30
+ '''Run qemu-nbd in daemon mode and return both the parent's exit code
31
+ and its output'''
32
+ subp = subprocess.Popen(qemu_nbd_args + ['--fork'] + list(args),
33
+ stdout=subprocess.PIPE,
34
+ stderr=subprocess.STDOUT,
35
+ universal_newlines=True)
36
+ exitcode = subp.wait()
37
+ if exitcode < 0:
38
+ sys.stderr.write('qemu-nbd received signal %i: %s\n' %
39
+ (-exitcode,
40
+ ' '.join(qemu_nbd_args + ['--fork'] + list(args))))
41
+ return exitcode, subp.communicate()[0]
42
+
43
def compare_images(img1, img2, fmt1=imgfmt, fmt2=imgfmt):
44
'''Return True if two image files are identical'''
45
return qemu_img('compare', '-f', fmt1,
46
--
47
2.20.1
48
49
diff view generated by jsdifflib
1
By default, qemu-nbd binds to 0.0.0.0. However, we then proceed to
1
From: Akihiko Odaki <akihiko.odaki@gmail.com>
2
connect to "localhost". Usually, this works out fine; but if this test
3
is run concurrently, some other test function may have bound a different
4
server to ::1 (on the same port -- you can bind different serves to the
5
same port, as long as one is on IPv4 and the other on IPv6).
6
2
7
So running qemu-nbd works, it can bind to 0.0.0.0:NBD_PORT. But
3
Signed-off-by: Akihiko Odaki <akihiko.odaki@gmail.com>
8
potentially a concurrent test has successfully taken [::1]:NBD_PORT. In
4
Message-id: 20210705130458.97642-3-akihiko.odaki@gmail.com
9
this case, trying to connect to "localhost" will lead us to the IPv6
5
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
10
instance, where we do not want to end up.
6
---
7
block/io.c | 2 ++
8
1 file changed, 2 insertions(+)
11
9
12
Fix this by just binding to "localhost". This will make qemu-nbd error
10
diff --git a/block/io.c b/block/io.c
13
out immediately and not give us cryptic errors later.
11
index XXXXXXX..XXXXXXX 100644
12
--- a/block/io.c
13
+++ b/block/io.c
14
@@ -XXX,XX +XXX,XX @@ void bdrv_parent_drained_begin_single(BdrvChild *c, bool poll)
15
16
static void bdrv_merge_limits(BlockLimits *dst, const BlockLimits *src)
17
{
18
+ dst->pdiscard_alignment = MAX(dst->pdiscard_alignment,
19
+ src->pdiscard_alignment);
20
dst->opt_transfer = MAX(dst->opt_transfer, src->opt_transfer);
21
dst->max_transfer = MIN_NON_ZERO(dst->max_transfer, src->max_transfer);
22
dst->max_hw_transfer = MIN_NON_ZERO(dst->max_hw_transfer,
23
--
24
2.31.1
14
25
15
(Also, it will allow us to just try a different port as of a future
16
patch.)
17
18
Signed-off-by: Max Reitz <mreitz@redhat.com>
19
Message-id: 20181221234750.23577-3-mreitz@redhat.com
20
Reviewed-by: John Snow <jsnow@redhat.com>
21
Reviewed-by: Eric Blake <eblake@redhat.com>
22
Signed-off-by: Max Reitz <mreitz@redhat.com>
23
---
24
tests/qemu-iotests/147 | 2 +-
25
1 file changed, 1 insertion(+), 1 deletion(-)
26
27
diff --git a/tests/qemu-iotests/147 b/tests/qemu-iotests/147
28
index XXXXXXX..XXXXXXX 100755
29
--- a/tests/qemu-iotests/147
30
+++ b/tests/qemu-iotests/147
31
@@ -XXX,XX +XXX,XX @@ class QemuNBD(NBDBlockdevAddBase):
32
self.assertEqual(qemu_nbd('-f', imgfmt, test_img, *args), 0)
33
34
def test_inet(self):
35
- self._server_up('-p', str(NBD_PORT))
36
+ self._server_up('-b', 'localhost', '-p', str(NBD_PORT))
37
address = { 'type': 'inet',
38
'data': {
39
'host': 'localhost',
40
--
41
2.20.1
42
43
diff view generated by jsdifflib