From a06b1dae4706fccb9394b35e88d1905dabec85e7 Mon Sep 17 00:00:00 2001 From: Sascha Silbe Date: Tue, 27 Sep 2016 15:43:37 +0200 Subject: virtio-serial: enable virtio console emergency write feature Add support for enabling the virtio 1.0 "emergency write" (VIRTIO_CONSOLE_F_EMERG_WRITE) feature. The previous patch introduced the plumbing required for this; now we expose the virtio feature to the guest. The feature is disabled for compatibility machines to avoid exposing a new feature to existing guests. As required by the virtio 1.0 spec, the emergency write functionality is available to the guest even if the guest doesn't negotatiate the feature, as well as before feature negotation. Reviewed-by: Cornelia Huck Signed-off-by: Sascha Silbe Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- include/hw/compat.h | 4 ++++ include/hw/virtio/virtio-serial.h | 2 ++ 2 files changed, 6 insertions(+) (limited to 'include') diff --git a/include/hw/compat.h b/include/hw/compat.h index 46412b229a..ef3fae3e1b 100644 --- a/include/hw/compat.h +++ b/include/hw/compat.h @@ -6,6 +6,10 @@ .driver = "virtio-pci",\ .property = "page-per-vq",\ .value = "on",\ + },{\ + .driver = "virtio-serial-device",\ + .property = "emergency-write",\ + .value = "off",\ },{\ .driver = "ioapic",\ .property = "version",\ diff --git a/include/hw/virtio/virtio-serial.h b/include/hw/virtio/virtio-serial.h index 730c88d2a7..b19c44727f 100644 --- a/include/hw/virtio/virtio-serial.h +++ b/include/hw/virtio/virtio-serial.h @@ -184,6 +184,8 @@ struct VirtIOSerial { struct VirtIOSerialPostLoad *post_load; virtio_serial_conf serial; + + uint64_t host_features; }; /* Interface to the virtio-serial bus */ -- cgit v1.2.3-55-g7522 From 6bea1ddf8b411dcb0ba5d3a83c4479492185a409 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Wed, 5 Oct 2016 17:51:23 +0200 Subject: numa: reduce code duplication by adding helper numa_get_node_for_cpu() Replace repeated pattern for (i = 0; i < nb_numa_nodes; i++) { if (test_bit(idx, numa_info[i].node_cpu)) { ... break; with a helper function to lookup numa node index for cpu. Suggested-by: Michael S. Tsirkin Signed-off-by: Igor Mammedov Reviewed-by: David Gibson Reviewed-by: Shannon Zhao Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/arm/virt-acpi-build.c | 6 ++---- hw/arm/virt.c | 7 +++---- hw/i386/acpi-build.c | 7 ++----- hw/i386/pc.c | 8 +++----- hw/ppc/spapr_cpu_core.c | 6 ++---- include/sysemu/numa.h | 3 +++ numa.c | 12 ++++++++++++ 7 files changed, 27 insertions(+), 22 deletions(-) (limited to 'include') diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c index 7b39b1d2d6..c77525d33a 100644 --- a/hw/arm/virt-acpi-build.c +++ b/hw/arm/virt-acpi-build.c @@ -427,11 +427,9 @@ build_srat(GArray *table_data, BIOSLinker *linker, VirtGuestInfo *guest_info) uint32_t *cpu_node = g_malloc0(guest_info->smp_cpus * sizeof(uint32_t)); for (i = 0; i < guest_info->smp_cpus; i++) { - for (j = 0; j < nb_numa_nodes; j++) { - if (test_bit(i, numa_info[j].node_cpu)) { + j = numa_get_node_for_cpu(i); + if (j < nb_numa_nodes) { cpu_node[i] = j; - break; - } } } diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 0f6305d3c7..795740d9bf 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -413,10 +413,9 @@ static void fdt_add_cpu_nodes(const VirtBoardInfo *vbi) armcpu->mp_affinity); } - for (i = 0; i < nb_numa_nodes; i++) { - if (test_bit(cpu, numa_info[i].node_cpu)) { - qemu_fdt_setprop_cell(vbi->fdt, nodename, "numa-node-id", i); - } + i = numa_get_node_for_cpu(cpu); + if (i < nb_numa_nodes) { + qemu_fdt_setprop_cell(vbi->fdt, nodename, "numa-node-id", i); } g_free(nodename); diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index c20bc71a67..e9996549cc 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -2410,18 +2410,15 @@ build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine) srat->reserved1 = cpu_to_le32(1); for (i = 0; i < apic_ids->len; i++) { - int j; + int j = numa_get_node_for_cpu(i); int apic_id = apic_ids->cpus[i].arch_id; core = acpi_data_push(table_data, sizeof *core); core->type = ACPI_SRAT_PROCESSOR_APIC; core->length = sizeof(*core); core->local_apic_id = apic_id; - for (j = 0; j < nb_numa_nodes; j++) { - if (test_bit(i, numa_info[j].node_cpu)) { + if (j < nb_numa_nodes) { core->proximity_lo = j; - break; - } } memset(core->proximity_hi, 0, 3); core->local_sapic_eid = 0; diff --git a/hw/i386/pc.c b/hw/i386/pc.c index 2d6d7920ff..93ff49c60b 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -779,11 +779,9 @@ static FWCfgState *bochs_bios_init(AddressSpace *as, PCMachineState *pcms) for (i = 0; i < max_cpus; i++) { unsigned int apic_id = x86_cpu_apic_id_from_index(i); assert(apic_id < pcms->apic_id_limit); - for (j = 0; j < nb_numa_nodes; j++) { - if (test_bit(i, numa_info[j].node_cpu)) { - numa_fw_cfg[apic_id + 1] = cpu_to_le64(j); - break; - } + j = numa_get_node_for_cpu(i); + if (j < nb_numa_nodes) { + numa_fw_cfg[apic_id + 1] = cpu_to_le64(j); } } for (i = 0; i < nb_numa_nodes; i++) { diff --git a/hw/ppc/spapr_cpu_core.c b/hw/ppc/spapr_cpu_core.c index 35d1873b9f..bc922bc86f 100644 --- a/hw/ppc/spapr_cpu_core.c +++ b/hw/ppc/spapr_cpu_core.c @@ -69,11 +69,9 @@ void spapr_cpu_init(sPAPRMachineState *spapr, PowerPCCPU *cpu, Error **errp) } /* Set NUMA node for the added CPUs */ - for (i = 0; i < nb_numa_nodes; i++) { - if (test_bit(cs->cpu_index, numa_info[i].node_cpu)) { + i = numa_get_node_for_cpu(cs->cpu_index); + if (i < nb_numa_nodes) { cs->numa_node = i; - break; - } } xics_cpu_setup(spapr->xics, cpu); diff --git a/include/sysemu/numa.h b/include/sysemu/numa.h index bb184c9cfe..4da808a6e9 100644 --- a/include/sysemu/numa.h +++ b/include/sysemu/numa.h @@ -32,4 +32,7 @@ void numa_set_mem_node_id(ram_addr_t addr, uint64_t size, uint32_t node); void numa_unset_mem_node_id(ram_addr_t addr, uint64_t size, uint32_t node); uint32_t numa_get_node(ram_addr_t addr, Error **errp); +/* on success returns node index in numa_info, + * on failure returns nb_numa_nodes */ +int numa_get_node_for_cpu(int idx); #endif diff --git a/numa.c b/numa.c index 6289f469bd..9c09e45e7d 100644 --- a/numa.c +++ b/numa.c @@ -550,3 +550,15 @@ MemdevList *qmp_query_memdev(Error **errp) object_child_foreach(obj, query_memdev, &list); return list; } + +int numa_get_node_for_cpu(int idx) +{ + int i; + + for (i = 0; i < nb_numa_nodes; i++) { + if (test_bit(idx, numa_info[i].node_cpu)) { + break; + } + } + return i; +} -- cgit v1.2.3-55-g7522 From 2640d2a5ff08978d67bd87518d05d6b499488c9a Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Mon, 19 Sep 2016 14:28:03 +0100 Subject: virtio: add virtio_detach_element() During device reset or similar situations a VirtQueueElement needs to be freed without pushing it onto the used ring or rewinding the virtqueue. Extract a new function to do this. Later patches add virtio_detach_element() calls to existing device so that scatter-gather lists are unmapped and vq->inuse goes back to zero during device reset. Currently some devices don't bother and simply call g_free(elem) which is not a clean way to throw away a VirtQueueElement. Signed-off-by: Stefan Hajnoczi Acked-by: Greg Kurz Reviewed-by: Ladi Prosek Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/virtio/virtio.c | 27 +++++++++++++++++++++++++-- include/hw/virtio/virtio.h | 2 ++ 2 files changed, 27 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c index 18ce333457..46f79c9e14 100644 --- a/hw/virtio/virtio.c +++ b/hw/virtio/virtio.c @@ -264,12 +264,35 @@ static void virtqueue_unmap_sg(VirtQueue *vq, const VirtQueueElement *elem, 0, elem->out_sg[i].iov_len); } +/* virtqueue_detach_element: + * @vq: The #VirtQueue + * @elem: The #VirtQueueElement + * @len: number of bytes written + * + * Detach the element from the virtqueue. This function is suitable for device + * reset or other situations where a #VirtQueueElement is simply freed and will + * not be pushed or discarded. + */ +void virtqueue_detach_element(VirtQueue *vq, const VirtQueueElement *elem, + unsigned int len) +{ + vq->inuse--; + virtqueue_unmap_sg(vq, elem, len); +} + +/* virtqueue_discard: + * @vq: The #VirtQueue + * @elem: The #VirtQueueElement + * @len: number of bytes written + * + * Pretend the most recent element wasn't popped from the virtqueue. The next + * call to virtqueue_pop() will refetch the element. + */ void virtqueue_discard(VirtQueue *vq, const VirtQueueElement *elem, unsigned int len) { vq->last_avail_idx--; - vq->inuse--; - virtqueue_unmap_sg(vq, elem, len); + virtqueue_detach_element(vq, elem, len); } /* virtqueue_rewind: diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h index 888c8debe6..e25ec4f0b5 100644 --- a/include/hw/virtio/virtio.h +++ b/include/hw/virtio/virtio.h @@ -155,6 +155,8 @@ void *virtqueue_alloc_element(size_t sz, unsigned out_num, unsigned in_num); void virtqueue_push(VirtQueue *vq, const VirtQueueElement *elem, unsigned int len); void virtqueue_flush(VirtQueue *vq, unsigned int count); +void virtqueue_detach_element(VirtQueue *vq, const VirtQueueElement *elem, + unsigned int len); void virtqueue_discard(VirtQueue *vq, const VirtQueueElement *elem, unsigned int len); bool virtqueue_rewind(VirtQueue *vq, unsigned int num); -- cgit v1.2.3-55-g7522 From d14dde5ec7a38df2e00a6f1b58e96ba38359dbb0 Mon Sep 17 00:00:00 2001 From: Greg Kurz Date: Fri, 30 Sep 2016 17:12:50 +0200 Subject: virtio-blk: make some functions static Some functions that were called from the dataplane code are now only used locally: virtio_blk_init_request() virtio_blk_handle_request() virtio_blk_submit_multireq() since commit "03de2f527499 virtio-blk: do not use vring in dataplane", and virtio_blk_free_request() since commit "6aa46d8ff1ee virtio: move VirtQueueElement at the beginning of the structs". This patch converts them to static. Signed-off-by: Greg Kurz Reviewed-by: Stefan Hajnoczi Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/block/virtio-blk.c | 10 +++++----- include/hw/virtio/virtio-blk.h | 8 -------- 2 files changed, 5 insertions(+), 13 deletions(-) (limited to 'include') diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c index c7ca4d6769..bbacd562ce 100644 --- a/hw/block/virtio-blk.c +++ b/hw/block/virtio-blk.c @@ -29,8 +29,8 @@ #include "hw/virtio/virtio-bus.h" #include "hw/virtio/virtio-access.h" -void virtio_blk_init_request(VirtIOBlock *s, VirtQueue *vq, - VirtIOBlockReq *req) +static void virtio_blk_init_request(VirtIOBlock *s, VirtQueue *vq, + VirtIOBlockReq *req) { req->dev = s; req->vq = vq; @@ -40,7 +40,7 @@ void virtio_blk_init_request(VirtIOBlock *s, VirtQueue *vq, req->mr_next = NULL; } -void virtio_blk_free_request(VirtIOBlockReq *req) +static void virtio_blk_free_request(VirtIOBlockReq *req) { if (req) { g_free(req); @@ -381,7 +381,7 @@ static int multireq_compare(const void *a, const void *b) } } -void virtio_blk_submit_multireq(BlockBackend *blk, MultiReqBuffer *mrb) +static void virtio_blk_submit_multireq(BlockBackend *blk, MultiReqBuffer *mrb) { int i = 0, start = 0, num_reqs = 0, niov = 0, nb_sectors = 0; uint32_t max_transfer; @@ -468,7 +468,7 @@ static bool virtio_blk_sect_range_ok(VirtIOBlock *dev, return true; } -void virtio_blk_handle_request(VirtIOBlockReq *req, MultiReqBuffer *mrb) +static void virtio_blk_handle_request(VirtIOBlockReq *req, MultiReqBuffer *mrb) { uint32_t type; struct iovec *in_iov = req->elem.in_sg; diff --git a/include/hw/virtio/virtio-blk.h b/include/hw/virtio/virtio-blk.h index 180bd8db5d..9734b4c446 100644 --- a/include/hw/virtio/virtio-blk.h +++ b/include/hw/virtio/virtio-blk.h @@ -80,14 +80,6 @@ typedef struct MultiReqBuffer { bool is_write; } MultiReqBuffer; -void virtio_blk_init_request(VirtIOBlock *s, VirtQueue *vq, - VirtIOBlockReq *req); -void virtio_blk_free_request(VirtIOBlockReq *req); - -void virtio_blk_handle_request(VirtIOBlockReq *req, MultiReqBuffer *mrb); - -void virtio_blk_submit_multireq(BlockBackend *blk, MultiReqBuffer *mrb); - void virtio_blk_handle_vq(VirtIOBlock *s, VirtQueue *vq); #endif -- cgit v1.2.3-55-g7522 From 0a73336d96397c80881219d080518fac6f1ecacb Mon Sep 17 00:00:00 2001 From: Daniel P. Berrange Date: Fri, 7 Oct 2016 13:18:34 +0100 Subject: net: don't poke at chardev internal QemuOpts The vhost-user & colo code is poking at the QemuOpts instance in the CharDriverState struct, not realizing that it is valid for this to be NULL. e.g. the following crash shows a codepath where it will be NULL: Program terminated with signal SIGSEGV, Segmentation fault. #0 0x000055baf6ab4adc in qemu_opt_foreach (opts=0x0, func=0x55baf696b650 , opaque=0x7ffc51368c00, errp=0x7ffc51368e48) at util/qemu-option.c:617 617 QTAILQ_FOREACH(opt, &opts->head, next) { [Current thread is 1 (Thread 0x7f1d4970bb40 (LWP 6603))] (gdb) bt #0 0x000055baf6ab4adc in qemu_opt_foreach (opts=0x0, func=0x55baf696b650 , opaque=0x7ffc51368c00, errp=0x7ffc51368e48) at util/qemu-option.c:617 #1 0x000055baf696b7da in net_vhost_parse_chardev (opts=0x55baf8ff9260, errp=0x7ffc51368e48) at net/vhost-user.c:314 #2 0x000055baf696b985 in net_init_vhost_user (netdev=0x55baf8ff9250, name=0x55baf879d270 "hostnet2", peer=0x0, errp=0x7ffc51368e48) at net/vhost-user.c:360 #3 0x000055baf6960216 in net_client_init1 (object=0x55baf8ff9250, is_netdev=true, errp=0x7ffc51368e48) at net/net.c:1051 #4 0x000055baf6960518 in net_client_init (opts=0x55baf776e7e0, is_netdev=true, errp=0x7ffc51368f00) at net/net.c:1108 #5 0x000055baf696083f in netdev_add (opts=0x55baf776e7e0, errp=0x7ffc51368f00) at net/net.c:1186 #6 0x000055baf69608c7 in qmp_netdev_add (qdict=0x55baf7afaf60, ret=0x7ffc51368f50, errp=0x7ffc51368f48) at net/net.c:1205 #7 0x000055baf6622135 in handle_qmp_command (parser=0x55baf77fb590, tokens=0x7f1d24011960) at /path/to/qemu.git/monitor.c:3978 #8 0x000055baf6a9d099 in json_message_process_token (lexer=0x55baf77fb598, input=0x55baf75acd20, type=JSON_RCURLY, x=113, y=19) at qobject/json-streamer.c:105 #9 0x000055baf6abf7aa in json_lexer_feed_char (lexer=0x55baf77fb598, ch=125 '}', flush=false) at qobject/json-lexer.c:319 #10 0x000055baf6abf8f2 in json_lexer_feed (lexer=0x55baf77fb598, buffer=0x7ffc51369170 "}R\204\367\272U", size=1) at qobject/json-lexer.c:369 #11 0x000055baf6a9d13c in json_message_parser_feed (parser=0x55baf77fb590, buffer=0x7ffc51369170 "}R\204\367\272U", size=1) at qobject/json-streamer.c:124 #12 0x000055baf66221f7 in monitor_qmp_read (opaque=0x55baf77fb530, buf=0x7ffc51369170 "}R\204\367\272U", size=1) at /path/to/qemu.git/monitor.c:3994 #13 0x000055baf6757014 in qemu_chr_be_write_impl (s=0x55baf7610a40, buf=0x7ffc51369170 "}R\204\367\272U", len=1) at qemu-char.c:387 #14 0x000055baf6757076 in qemu_chr_be_write (s=0x55baf7610a40, buf=0x7ffc51369170 "}R\204\367\272U", len=1) at qemu-char.c:399 #15 0x000055baf675b3b0 in tcp_chr_read (chan=0x55baf90244b0, cond=G_IO_IN, opaque=0x55baf7610a40) at qemu-char.c:2927 #16 0x000055baf6a5d655 in qio_channel_fd_source_dispatch (source=0x55baf7610df0, callback=0x55baf675b25a , user_data=0x55baf7610a40) at io/channel-watch.c:84 #17 0x00007f1d3e80cbbd in g_main_context_dispatch () from /usr/lib64/libglib-2.0.so.0 #18 0x000055baf69d3720 in glib_pollfds_poll () at main-loop.c:213 #19 0x000055baf69d37fd in os_host_main_loop_wait (timeout=126000000) at main-loop.c:258 #20 0x000055baf69d38ad in main_loop_wait (nonblocking=0) at main-loop.c:506 #21 0x000055baf676587b in main_loop () at vl.c:1908 #22 0x000055baf676d3bf in main (argc=101, argv=0x7ffc5136a6c8, envp=0x7ffc5136a9f8) at vl.c:4604 (gdb) p opts $1 = (QemuOpts *) 0x0 The crash occurred when attaching vhost-user net via QMP: { "execute": "chardev-add", "arguments": { "id": "charnet2", "backend": { "type": "socket", "data": { "addr": { "type": "unix", "data": { "path": "/var/run/openvswitch/vhost-user1" } }, "wait": false, "server": false } } }, "id": "libvirt-19" } { "return": { }, "id": "libvirt-19" } { "execute": "netdev_add", "arguments": { "type": "vhost-user", "chardev": "charnet2", "id": "hostnet2" }, "id": "libvirt-20" } Code using chardevs should not be poking at the internals of the CharDriverState struct. What vhost-user wants is a chardev that is operating as reconnectable network service, along with the ability to do FD passing over the connection. The colo code simply wants a network service. Add a feature concept to the char drivers so that chardev users can query the actual features they wish to have supported. The QemuOpts member is removed to prevent future mistakes in this area. Signed-off-by: Daniel P. Berrange Reviewed-by: Marc-André Lureau Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hmp.c | 1 + include/sysemu/char.h | 21 ++++++++++++++++++++- net/colo-compare.c | 30 ++---------------------------- net/vhost-user.c | 41 +++++++---------------------------------- qemu-char.c | 22 +++++++++++++++++++--- 5 files changed, 49 insertions(+), 66 deletions(-) (limited to 'include') diff --git a/hmp.c b/hmp.c index 336e7bf076..3c421828ff 100644 --- a/hmp.c +++ b/hmp.c @@ -1909,6 +1909,7 @@ void hmp_chardev_add(Monitor *mon, const QDict *qdict) error_setg(&err, "Parsing chardev args failed"); } else { qemu_chr_new_from_opts(opts, NULL, &err); + qemu_opts_del(opts); } hmp_handle_error(mon, &err); } diff --git a/include/sysemu/char.h b/include/sysemu/char.h index 0d0465ae0e..19dad3fb9c 100644 --- a/include/sysemu/char.h +++ b/include/sysemu/char.h @@ -9,6 +9,7 @@ #include "qapi/qmp/qobject.h" #include "qapi/qmp/qstring.h" #include "qemu/main-loop.h" +#include "qemu/bitmap.h" /* character device */ @@ -58,6 +59,20 @@ struct ParallelIOArg { typedef void IOEventHandler(void *opaque, int event); +typedef enum { + /* Whether the chardev peer is able to close and + * reopen the data channel, thus requiring support + * for qemu_chr_wait_connected() to wait for a + * valid connection */ + QEMU_CHAR_FEATURE_RECONNECTABLE, + /* Whether it is possible to send/recv file descriptors + * over the data channel */ + QEMU_CHAR_FEATURE_FD_PASS, + + QEMU_CHAR_FEATURE_LAST, +} CharDriverFeature; + + struct CharDriverState { QemuMutex chr_write_lock; void (*init)(struct CharDriverState *s); @@ -93,8 +108,8 @@ struct CharDriverState { int avail_connections; int is_mux; guint fd_in_tag; - QemuOpts *opts; bool replay; + DECLARE_BITMAP(features, QEMU_CHAR_FEATURE_LAST); QTAILQ_ENTRY(CharDriverState) next; }; @@ -437,6 +452,10 @@ int qemu_chr_add_client(CharDriverState *s, int fd); CharDriverState *qemu_chr_find(const char *name); bool chr_is_ringbuf(const CharDriverState *chr); +bool qemu_chr_has_feature(CharDriverState *chr, + CharDriverFeature feature); +void qemu_chr_set_feature(CharDriverState *chr, + CharDriverFeature feature); QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename); void register_char_driver(const char *name, ChardevBackendKind kind, diff --git a/net/colo-compare.c b/net/colo-compare.c index 22b1da19f5..47703c59bc 100644 --- a/net/colo-compare.c +++ b/net/colo-compare.c @@ -564,29 +564,6 @@ static void compare_sec_rs_finalize(SocketReadState *sec_rs) } } -static int compare_chardev_opts(void *opaque, - const char *name, const char *value, - Error **errp) -{ - CompareChardevProps *props = opaque; - - if (strcmp(name, "backend") == 0 && - strcmp(value, "socket") == 0) { - props->is_socket = true; - return 0; - } else if (strcmp(name, "host") == 0 || - (strcmp(name, "port") == 0) || - (strcmp(name, "server") == 0) || - (strcmp(name, "wait") == 0) || - (strcmp(name, "path") == 0)) { - return 0; - } else { - error_setg(errp, - "COLO-compare does not support a chardev with option %s=%s", - name, value); - return -1; - } -} /* * Return 0 is success. @@ -606,12 +583,9 @@ static int find_and_check_chardev(CharDriverState **chr, } memset(&props, 0, sizeof(props)); - if (qemu_opt_foreach((*chr)->opts, compare_chardev_opts, &props, errp)) { - return 1; - } - if (!props.is_socket) { - error_setg(errp, "chardev \"%s\" is not a tcp socket", + if (!qemu_chr_has_feature(*chr, QEMU_CHAR_FEATURE_RECONNECTABLE)) { + error_setg(errp, "chardev \"%s\" is not reconnectable", chr_name); return 1; } diff --git a/net/vhost-user.c b/net/vhost-user.c index b0595f8781..5b94c84541 100644 --- a/net/vhost-user.c +++ b/net/vhost-user.c @@ -27,11 +27,6 @@ typedef struct VhostUserState { bool started; } VhostUserState; -typedef struct VhostUserChardevProps { - bool is_socket; - bool is_unix; -} VhostUserChardevProps; - VHostNetState *vhost_user_get_vhost_net(NetClientState *nc) { VhostUserState *s = DO_UPCAST(VhostUserState, nc, nc); @@ -278,45 +273,23 @@ static int net_vhost_user_init(NetClientState *peer, const char *device, return 0; } -static int net_vhost_chardev_opts(void *opaque, - const char *name, const char *value, - Error **errp) -{ - VhostUserChardevProps *props = opaque; - - if (strcmp(name, "backend") == 0 && strcmp(value, "socket") == 0) { - props->is_socket = true; - } else if (strcmp(name, "path") == 0) { - props->is_unix = true; - } else if (strcmp(name, "server") == 0) { - } else { - error_setg(errp, - "vhost-user does not support a chardev with option %s=%s", - name, value); - return -1; - } - return 0; -} - -static CharDriverState *net_vhost_parse_chardev( +static CharDriverState *net_vhost_claim_chardev( const NetdevVhostUserOptions *opts, Error **errp) { CharDriverState *chr = qemu_chr_find(opts->chardev); - VhostUserChardevProps props; if (chr == NULL) { error_setg(errp, "chardev \"%s\" not found", opts->chardev); return NULL; } - /* inspect chardev opts */ - memset(&props, 0, sizeof(props)); - if (qemu_opt_foreach(chr->opts, net_vhost_chardev_opts, &props, errp)) { + if (!qemu_chr_has_feature(chr, QEMU_CHAR_FEATURE_RECONNECTABLE)) { + error_setg(errp, "chardev \"%s\" is not reconnectable", + opts->chardev); return NULL; } - - if (!props.is_socket || !props.is_unix) { - error_setg(errp, "chardev \"%s\" is not a unix socket", + if (!qemu_chr_has_feature(chr, QEMU_CHAR_FEATURE_FD_PASS)) { + error_setg(errp, "chardev \"%s\" does not support FD passing", opts->chardev); return NULL; } @@ -357,7 +330,7 @@ int net_init_vhost_user(const Netdev *netdev, const char *name, assert(netdev->type == NET_CLIENT_DRIVER_VHOST_USER); vhost_user_opts = &netdev->u.vhost_user; - chr = net_vhost_parse_chardev(vhost_user_opts, errp); + chr = net_vhost_claim_chardev(vhost_user_opts, errp); if (!chr) { return -1; } diff --git a/qemu-char.c b/qemu-char.c index fb456cec34..768150d1f8 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -3996,7 +3996,6 @@ CharDriverState *qemu_chr_new_from_opts(QemuOpts *opts, } chr = qemu_chr_find(id); - chr->opts = opts; qapi_out: qapi_free_ChardevBackend(backend); @@ -4005,7 +4004,6 @@ qapi_out: return chr; err: - qemu_opts_del(opts); return NULL; } @@ -4033,6 +4031,7 @@ CharDriverState *qemu_chr_new_noreplay(const char *label, const char *filename, qemu_chr_fe_claim_no_fail(chr); monitor_init(chr, MONITOR_USE_READLINE); } + qemu_opts_del(opts); return chr; } @@ -4132,7 +4131,6 @@ static void qemu_chr_free_common(CharDriverState *chr) { g_free(chr->filename); g_free(chr->label); - qemu_opts_del(chr->opts); if (chr->logfd != -1) { close(chr->logfd); } @@ -4513,6 +4511,11 @@ static CharDriverState *qmp_chardev_open_socket(const char *id, s->addr = QAPI_CLONE(SocketAddress, sock->addr); + qemu_chr_set_feature(chr, QEMU_CHAR_FEATURE_RECONNECTABLE); + if (s->is_unix) { + qemu_chr_set_feature(chr, QEMU_CHAR_FEATURE_FD_PASS); + } + chr->opaque = s; chr->chr_wait_connected = tcp_chr_wait_connected; chr->chr_write = tcp_chr_write; @@ -4596,6 +4599,19 @@ static CharDriverState *qmp_chardev_open_udp(const char *id, return qemu_chr_open_udp(sioc, common, errp); } + +bool qemu_chr_has_feature(CharDriverState *chr, + CharDriverFeature feature) +{ + return test_bit(feature, chr->features); +} + +void qemu_chr_set_feature(CharDriverState *chr, + CharDriverFeature feature) +{ + return set_bit(feature, chr->features); +} + ChardevReturn *qmp_chardev_add(const char *id, ChardevBackend *backend, Error **errp) { -- cgit v1.2.3-55-g7522 From 1a665855d7144bb3df382630a2b5e4039e95e466 Mon Sep 17 00:00:00 2001 From: Halil Pasic Date: Thu, 6 Oct 2016 14:55:39 +0200 Subject: virtio: prepare change VMSTATE_VIRTIO_DEVICE macro In most cases the functions passed to VMSTATE_VIRTIO_DEVICE only call the virtio_load and virtio_save wrappers. Some include some pre- and post- massaging too. The massaging is better expressed as such in the VMStateDescription. Let us prepare for changing the semantic of the VMSTATE_VIRTIO_DEVICE macro so that it is more similar to the other VMSTATE_*_DEVICE macros in a sense that it is a field definition. The preprocessor conditionals are going to be removed as soon as every usage is converted to the new semantic. Signed-off-by: Halil Pasic Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/virtio/virtio.c | 21 +++++++++++++++++++++ include/hw/virtio/virtio.h | 16 ++++++++++++++++ 2 files changed, 37 insertions(+) (limited to 'include') diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c index 46f79c9e14..62b9c002ff 100644 --- a/hw/virtio/virtio.c +++ b/hw/virtio/virtio.c @@ -1645,6 +1645,27 @@ void virtio_vmstate_save(QEMUFile *f, void *opaque, size_t size) virtio_save(VIRTIO_DEVICE(opaque), f); } +/* A wrapper for use as a VMState .put function */ +static void virtio_device_put(QEMUFile *f, void *opaque, size_t size) +{ + virtio_save(VIRTIO_DEVICE(opaque), f); +} + +/* A wrapper for use as a VMState .get function */ +static int virtio_device_get(QEMUFile *f, void *opaque, size_t size) +{ + VirtIODevice *vdev = VIRTIO_DEVICE(opaque); + DeviceClass *dc = DEVICE_CLASS(VIRTIO_DEVICE_GET_CLASS(vdev)); + + return virtio_load(vdev, f, dc->vmsd->version_id); +} + +const VMStateInfo virtio_vmstate_info = { + .name = "virtio", + .get = virtio_device_get, + .put = virtio_device_put, +}; + static int virtio_set_features_nocheck(VirtIODevice *vdev, uint64_t val) { VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h index e25ec4f0b5..929fa92c32 100644 --- a/include/hw/virtio/virtio.h +++ b/include/hw/virtio/virtio.h @@ -179,6 +179,20 @@ void virtio_notify(VirtIODevice *vdev, VirtQueue *vq); void virtio_save(VirtIODevice *vdev, QEMUFile *f); void virtio_vmstate_save(QEMUFile *f, void *opaque, size_t size); +extern const VMStateInfo virtio_vmstate_info; + +#ifdef VMSTATE_VIRTIO_DEVICE_USE_NEW + +#define VMSTATE_VIRTIO_DEVICE \ + { \ + .name = "virtio", \ + .info = &virtio_vmstate_info, \ + .flags = VMS_SINGLE, \ + } + +#else +/* TODO remove conditional as soon as all users are converted */ + #define VMSTATE_VIRTIO_DEVICE(devname, v, getf, putf) \ static const VMStateDescription vmstate_virtio_ ## devname = { \ .name = "virtio-" #devname , \ @@ -198,6 +212,8 @@ void virtio_vmstate_save(QEMUFile *f, void *opaque, size_t size); } \ } +#endif + int virtio_load(VirtIODevice *vdev, QEMUFile *f, int version_id); void virtio_notify_config(VirtIODevice *vdev); -- cgit v1.2.3-55-g7522 From 5705653ff8666ffb247971361904f902aa033351 Mon Sep 17 00:00:00 2001 From: Halil Pasic Date: Thu, 6 Oct 2016 14:55:50 +0200 Subject: virtio: cleanup VMSTATE_VIRTIO_DEVICE Now all the usages of the old version of VMSTATE_VIRTIO_DEVICE are gone, so we can get rid of the conditionals, and the old macro. Signed-off-by: Halil Pasic Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/9pfs/virtio-9p-device.c | 2 -- hw/block/virtio-blk.c | 2 -- hw/char/virtio-serial-bus.c | 2 -- hw/display/virtio-gpu.c | 2 -- hw/input/virtio-input.c | 2 -- hw/net/virtio-net.c | 2 -- hw/scsi/virtio-scsi.c | 2 -- hw/virtio/vhost-vsock.c | 2 -- hw/virtio/virtio-balloon.c | 2 -- hw/virtio/virtio-rng.c | 2 -- hw/virtio/virtio.c | 6 ------ include/hw/virtio/virtio.h | 27 --------------------------- 12 files changed, 53 deletions(-) (limited to 'include') diff --git a/hw/9pfs/virtio-9p-device.c b/hw/9pfs/virtio-9p-device.c index 526ec7d08f..e98dd0c4c0 100644 --- a/hw/9pfs/virtio-9p-device.c +++ b/hw/9pfs/virtio-9p-device.c @@ -11,8 +11,6 @@ * */ -#define VMSTATE_VIRTIO_DEVICE_USE_NEW - #include "qemu/osdep.h" #include "hw/virtio/virtio.h" #include "qemu/sockets.h" diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c index 10c5794063..37fe72bdcd 100644 --- a/hw/block/virtio-blk.c +++ b/hw/block/virtio-blk.c @@ -11,8 +11,6 @@ * */ -#define VMSTATE_VIRTIO_DEVICE_USE_NEW - #include "qemu/osdep.h" #include "qapi/error.h" #include "qemu-common.h" diff --git a/hw/char/virtio-serial-bus.c b/hw/char/virtio-serial-bus.c index c9b0fc8325..7975c2cda1 100644 --- a/hw/char/virtio-serial-bus.c +++ b/hw/char/virtio-serial-bus.c @@ -18,8 +18,6 @@ * GNU GPL, version 2 or (at your option) any later version. */ -#define VMSTATE_VIRTIO_DEVICE_USE_NEW - #include "qemu/osdep.h" #include "qapi/error.h" #include "qemu/iov.h" diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c index 4fcd63cdb6..fa6fd0e53f 100644 --- a/hw/display/virtio-gpu.c +++ b/hw/display/virtio-gpu.c @@ -11,8 +11,6 @@ * See the COPYING file in the top-level directory. */ -#define VMSTATE_VIRTIO_DEVICE_USE_NEW - #include "qemu/osdep.h" #include "qemu-common.h" #include "qemu/iov.h" diff --git a/hw/input/virtio-input.c b/hw/input/virtio-input.c index 5e31033c4d..b678ee9f20 100644 --- a/hw/input/virtio-input.c +++ b/hw/input/virtio-input.c @@ -4,8 +4,6 @@ * top-level directory. */ -#define VMSTATE_VIRTIO_DEVICE_USE_NEW - #include "qemu/osdep.h" #include "qapi/error.h" #include "qemu/iov.h" diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c index b2198a550e..06bfe4bcc9 100644 --- a/hw/net/virtio-net.c +++ b/hw/net/virtio-net.c @@ -11,8 +11,6 @@ * */ -#define VMSTATE_VIRTIO_DEVICE_USE_NEW - #include "qemu/osdep.h" #include "qemu/iov.h" #include "hw/virtio/virtio.h" diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c index 9473e1099f..4762f05274 100644 --- a/hw/scsi/virtio-scsi.c +++ b/hw/scsi/virtio-scsi.c @@ -13,8 +13,6 @@ * */ -#define VMSTATE_VIRTIO_DEVICE_USE_NEW - #include "qemu/osdep.h" #include "qapi/error.h" #include "standard-headers/linux/virtio_ids.h" diff --git a/hw/virtio/vhost-vsock.c b/hw/virtio/vhost-vsock.c index 99cb216ae1..b4815629e1 100644 --- a/hw/virtio/vhost-vsock.c +++ b/hw/virtio/vhost-vsock.c @@ -11,8 +11,6 @@ * top-level directory. */ -#define VMSTATE_VIRTIO_DEVICE_USE_NEW - #include #include "qemu/osdep.h" #include "standard-headers/linux/virtio_vsock.h" diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c index 2c68d3dc5f..1d77028236 100644 --- a/hw/virtio/virtio-balloon.c +++ b/hw/virtio/virtio-balloon.c @@ -13,8 +13,6 @@ * */ -#define VMSTATE_VIRTIO_DEVICE_USE_NEW - #include "qemu/osdep.h" #include "qemu/iov.h" #include "qemu/timer.h" diff --git a/hw/virtio/virtio-rng.c b/hw/virtio/virtio-rng.c index 62867d141e..9639f4e89b 100644 --- a/hw/virtio/virtio-rng.c +++ b/hw/virtio/virtio-rng.c @@ -9,8 +9,6 @@ * top-level directory. */ -#define VMSTATE_VIRTIO_DEVICE_USE_NEW - #include "qemu/osdep.h" #include "qapi/error.h" #include "qemu/iov.h" diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c index 62b9c002ff..d48d1a98a7 100644 --- a/hw/virtio/virtio.c +++ b/hw/virtio/virtio.c @@ -1639,12 +1639,6 @@ void virtio_save(VirtIODevice *vdev, QEMUFile *f) vmstate_save_state(f, &vmstate_virtio, vdev, NULL); } -/* A wrapper for use as a VMState .put function */ -void virtio_vmstate_save(QEMUFile *f, void *opaque, size_t size) -{ - virtio_save(VIRTIO_DEVICE(opaque), f); -} - /* A wrapper for use as a VMState .put function */ static void virtio_device_put(QEMUFile *f, void *opaque, size_t size) { diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h index 929fa92c32..b913aac455 100644 --- a/include/hw/virtio/virtio.h +++ b/include/hw/virtio/virtio.h @@ -177,12 +177,9 @@ bool virtio_should_notify(VirtIODevice *vdev, VirtQueue *vq); void virtio_notify(VirtIODevice *vdev, VirtQueue *vq); void virtio_save(VirtIODevice *vdev, QEMUFile *f); -void virtio_vmstate_save(QEMUFile *f, void *opaque, size_t size); extern const VMStateInfo virtio_vmstate_info; -#ifdef VMSTATE_VIRTIO_DEVICE_USE_NEW - #define VMSTATE_VIRTIO_DEVICE \ { \ .name = "virtio", \ @@ -190,30 +187,6 @@ extern const VMStateInfo virtio_vmstate_info; .flags = VMS_SINGLE, \ } -#else -/* TODO remove conditional as soon as all users are converted */ - -#define VMSTATE_VIRTIO_DEVICE(devname, v, getf, putf) \ - static const VMStateDescription vmstate_virtio_ ## devname = { \ - .name = "virtio-" #devname , \ - .minimum_version_id = v, \ - .version_id = v, \ - .fields = (VMStateField[]) { \ - { \ - .name = "virtio", \ - .info = &(const VMStateInfo) {\ - .name = "virtio", \ - .get = getf, \ - .put = putf, \ - }, \ - .flags = VMS_SINGLE, \ - }, \ - VMSTATE_END_OF_LIST() \ - } \ - } - -#endif - int virtio_load(VirtIODevice *vdev, QEMUFile *f, int version_id); void virtio_notify_config(VirtIODevice *vdev); -- cgit v1.2.3-55-g7522