diff options
| author | Peter Maydell <peter.maydell@linaro.org> | 2019-01-31 19:26:09 +0000 |
|---|---|---|
| committer | Peter Maydell <peter.maydell@linaro.org> | 2019-01-31 19:26:09 +0000 |
| commit | cfe6c547690b06fbce54a6d0f7b05dd7f18e36ea (patch) | |
| tree | 103fb713da1c3ba222cb025f7b47899fb339596f /block.c | |
| parent | e8977901b79fb678f288dd372261b640bbeccd0d (diff) | |
| parent | 908b30164bbffad7430d551b2a03a8fbcaa631ef (diff) | |
| download | focaccia-qemu-cfe6c547690b06fbce54a6d0f7b05dd7f18e36ea.tar.gz focaccia-qemu-cfe6c547690b06fbce54a6d0f7b05dd7f18e36ea.zip | |
Merge remote-tracking branch 'remotes/xanclic/tags/pull-block-2019-01-31' into staging
Block patches: - New debugging QMP command to explore block graphs - Converted DPRINTF()s to trace events - Fixed qemu-io's use of getopt() for systems with optreset - Minor NVMe emulation fixes - An iotest fix # gpg: Signature made Thu 31 Jan 2019 00:51:46 GMT # gpg: using RSA key F407DB0061D5CF40 # gpg: Good signature from "Max Reitz <mreitz@redhat.com>" [full] # Primary key fingerprint: 91BE B60A 30DB 3E88 57D1 1829 F407 DB00 61D5 CF40 * remotes/xanclic/tags/pull-block-2019-01-31: iotests: Allow 147 to be run concurrently iotests: Bind qemu-nbd to localhost in 147 iotests.py: Add qemu_nbd_pipe() nvme: use pci_dev directly in nvme_realize nvme: ensure the num_queues is not zero nvme: use TYPE_NVME instead of constant string qemu-io: Add generic function for reinitializing optind. block/sheepdog: Convert from DPRINTF() macro to trace events block/file-posix: Convert from DPRINTF() macro to trace events block/curl: Convert from DPRINTF() macro to trace events block/ssh: Convert from DPRINTF() macro to trace events scripts: add render_block_graph function for QEMUMachine qapi: add x-debug-query-block-graph Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'block.c')
| -rw-r--r-- | block.c | 148 |
1 files changed, 148 insertions, 0 deletions
diff --git a/block.c b/block.c index 4f5ff2cc12..e795a7c5de 100644 --- a/block.c +++ b/block.c @@ -4119,6 +4119,154 @@ BlockDeviceInfoList *bdrv_named_nodes_list(Error **errp) return list; } +#define QAPI_LIST_ADD(list, element) do { \ + typeof(list) _tmp = g_new(typeof(*(list)), 1); \ + _tmp->value = (element); \ + _tmp->next = (list); \ + (list) = _tmp; \ +} while (0) + +typedef struct XDbgBlockGraphConstructor { + XDbgBlockGraph *graph; + GHashTable *graph_nodes; +} XDbgBlockGraphConstructor; + +static XDbgBlockGraphConstructor *xdbg_graph_new(void) +{ + XDbgBlockGraphConstructor *gr = g_new(XDbgBlockGraphConstructor, 1); + + gr->graph = g_new0(XDbgBlockGraph, 1); + gr->graph_nodes = g_hash_table_new(NULL, NULL); + + return gr; +} + +static XDbgBlockGraph *xdbg_graph_finalize(XDbgBlockGraphConstructor *gr) +{ + XDbgBlockGraph *graph = gr->graph; + + g_hash_table_destroy(gr->graph_nodes); + g_free(gr); + + return graph; +} + +static uintptr_t xdbg_graph_node_num(XDbgBlockGraphConstructor *gr, void *node) +{ + uintptr_t ret = (uintptr_t)g_hash_table_lookup(gr->graph_nodes, node); + + if (ret != 0) { + return ret; + } + + /* + * Start counting from 1, not 0, because 0 interferes with not-found (NULL) + * answer of g_hash_table_lookup. + */ + ret = g_hash_table_size(gr->graph_nodes) + 1; + g_hash_table_insert(gr->graph_nodes, node, (void *)ret); + + return ret; +} + +static void xdbg_graph_add_node(XDbgBlockGraphConstructor *gr, void *node, + XDbgBlockGraphNodeType type, const char *name) +{ + XDbgBlockGraphNode *n; + + n = g_new0(XDbgBlockGraphNode, 1); + + n->id = xdbg_graph_node_num(gr, node); + n->type = type; + n->name = g_strdup(name); + + QAPI_LIST_ADD(gr->graph->nodes, n); +} + +static void xdbg_graph_add_edge(XDbgBlockGraphConstructor *gr, void *parent, + const BdrvChild *child) +{ + typedef struct { + unsigned int flag; + BlockPermission num; + } PermissionMap; + + static const PermissionMap permissions[] = { + { BLK_PERM_CONSISTENT_READ, BLOCK_PERMISSION_CONSISTENT_READ }, + { BLK_PERM_WRITE, BLOCK_PERMISSION_WRITE }, + { BLK_PERM_WRITE_UNCHANGED, BLOCK_PERMISSION_WRITE_UNCHANGED }, + { BLK_PERM_RESIZE, BLOCK_PERMISSION_RESIZE }, + { BLK_PERM_GRAPH_MOD, BLOCK_PERMISSION_GRAPH_MOD }, + { 0, 0 } + }; + const PermissionMap *p; + XDbgBlockGraphEdge *edge; + + QEMU_BUILD_BUG_ON(1UL << (ARRAY_SIZE(permissions) - 1) != BLK_PERM_ALL + 1); + + edge = g_new0(XDbgBlockGraphEdge, 1); + + edge->parent = xdbg_graph_node_num(gr, parent); + edge->child = xdbg_graph_node_num(gr, child->bs); + edge->name = g_strdup(child->name); + + for (p = permissions; p->flag; p++) { + if (p->flag & child->perm) { + QAPI_LIST_ADD(edge->perm, p->num); + } + if (p->flag & child->shared_perm) { + QAPI_LIST_ADD(edge->shared_perm, p->num); + } + } + + QAPI_LIST_ADD(gr->graph->edges, edge); +} + + +XDbgBlockGraph *bdrv_get_xdbg_block_graph(Error **errp) +{ + BlockBackend *blk; + BlockJob *job; + BlockDriverState *bs; + BdrvChild *child; + XDbgBlockGraphConstructor *gr = xdbg_graph_new(); + + for (blk = blk_all_next(NULL); blk; blk = blk_all_next(blk)) { + char *allocated_name = NULL; + const char *name = blk_name(blk); + + if (!*name) { + name = allocated_name = blk_get_attached_dev_id(blk); + } + xdbg_graph_add_node(gr, blk, X_DBG_BLOCK_GRAPH_NODE_TYPE_BLOCK_BACKEND, + name); + g_free(allocated_name); + if (blk_root(blk)) { + xdbg_graph_add_edge(gr, blk, blk_root(blk)); + } + } + + for (job = block_job_next(NULL); job; job = block_job_next(job)) { + GSList *el; + + xdbg_graph_add_node(gr, job, X_DBG_BLOCK_GRAPH_NODE_TYPE_BLOCK_JOB, + job->job.id); + for (el = job->nodes; el; el = el->next) { + xdbg_graph_add_edge(gr, job, (BdrvChild *)el->data); + } + } + + QTAILQ_FOREACH(bs, &graph_bdrv_states, node_list) { + xdbg_graph_add_node(gr, bs, X_DBG_BLOCK_GRAPH_NODE_TYPE_BLOCK_DRIVER, + bs->node_name); + QLIST_FOREACH(child, &bs->children, next) { + xdbg_graph_add_edge(gr, bs, child); + } + } + + return xdbg_graph_finalize(gr); +} + BlockDriverState *bdrv_lookup_bs(const char *device, const char *node_name, Error **errp) |