diff options
-rw-r--r-- | blockdev-nbd.c | 3 | ||||
-rw-r--r-- | chardev/char-fe.c | 13 | ||||
-rw-r--r-- | chardev/char-io.c | 48 | ||||
-rw-r--r-- | chardev/char-socket.c | 8 | ||||
-rw-r--r-- | chardev/char.c | 37 | ||||
-rw-r--r-- | gdbstub.c | 6 | ||||
-rw-r--r-- | hw/char/xen_console.c | 6 | ||||
-rw-r--r-- | include/block/nbd.h | 7 | ||||
-rw-r--r-- | include/chardev/char-fe.h | 81 | ||||
-rw-r--r-- | include/chardev/char.h | 81 | ||||
-rw-r--r-- | nbd/client.c | 44 | ||||
-rw-r--r-- | nbd/server.c | 80 | ||||
-rw-r--r-- | net/slirp.c | 6 | ||||
-rw-r--r-- | qemu-nbd.c | 26 | ||||
-rwxr-xr-x | scripts/device-crash-test | 6 | ||||
-rwxr-xr-x | tests/docker/docker.py | 4 | ||||
-rw-r--r-- | tests/migration/guestperf/shell.py | 8 | ||||
-rw-r--r-- | vl.c | 10 |
18 files changed, 216 insertions, 258 deletions
diff --git a/blockdev-nbd.c b/blockdev-nbd.c index 1ef11041a7..1d170c80b8 100644 --- a/blockdev-nbd.c +++ b/blockdev-nbd.c @@ -36,8 +36,7 @@ static void nbd_accept(QIONetListener *listener, QIOChannelSocket *cioc, gpointer opaque) { qio_channel_set_name(QIO_CHANNEL(cioc), "nbd-server"); - nbd_client_new(NULL, cioc, - nbd_server->tlscreds, NULL, + nbd_client_new(cioc, nbd_server->tlscreds, NULL, nbd_blockdev_client_closed); } diff --git a/chardev/char-fe.c b/chardev/char-fe.c index b1f228e8b5..a8931f7afd 100644 --- a/chardev/char-fe.c +++ b/chardev/char-fe.c @@ -56,7 +56,7 @@ int qemu_chr_fe_write_all(CharBackend *be, const uint8_t *buf, int len) int qemu_chr_fe_read_all(CharBackend *be, uint8_t *buf, int len) { Chardev *s = be->chr; - int offset = 0, counter = 10; + int offset = 0; int res; if (!s || !CHARDEV_GET_CLASS(s)->chr_sync_read) { @@ -88,10 +88,6 @@ int qemu_chr_fe_read_all(CharBackend *be, uint8_t *buf, int len) } offset += res; - - if (!counter--) { - break; - } } if (qemu_chr_replay(s) && replay_mode == REPLAY_MODE_RECORD) { @@ -239,7 +235,12 @@ void qemu_chr_fe_deinit(CharBackend *b, bool del) d->backends[b->tag] = NULL; } if (del) { - object_unparent(OBJECT(b->chr)); + Object *obj = OBJECT(b->chr); + if (obj->parent) { + object_unparent(obj); + } else { + object_unref(obj); + } } b->chr = NULL; } diff --git a/chardev/char-io.c b/chardev/char-io.c index f81052481a..8ced184160 100644 --- a/chardev/char-io.c +++ b/chardev/char-io.c @@ -33,7 +33,6 @@ typedef struct IOWatchPoll { IOCanReadHandler *fd_can_read; GSourceFunc fd_read; void *opaque; - GMainContext *context; } IOWatchPoll; static IOWatchPoll *io_watch_poll_from_source(GSource *source) @@ -55,47 +54,24 @@ static gboolean io_watch_poll_prepare(GSource *source, iwp->src = qio_channel_create_watch( iwp->ioc, G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL); g_source_set_callback(iwp->src, iwp->fd_read, iwp->opaque, NULL); - g_source_attach(iwp->src, iwp->context); - } else { - g_source_destroy(iwp->src); + g_source_add_child_source(source, iwp->src); g_source_unref(iwp->src); + } else { + g_source_remove_child_source(source, iwp->src); iwp->src = NULL; } return FALSE; } -static gboolean io_watch_poll_check(GSource *source) -{ - return FALSE; -} - static gboolean io_watch_poll_dispatch(GSource *source, GSourceFunc callback, gpointer user_data) { - abort(); -} - -static void io_watch_poll_finalize(GSource *source) -{ - /* Due to a glib bug, removing the last reference to a source - * inside a finalize callback causes recursive locking (and a - * deadlock). This is not a problem inside other callbacks, - * including dispatch callbacks, so we call io_remove_watch_poll - * to remove this source. At this point, iwp->src must - * be NULL, or we would leak it. - * - * This would be solved much more elegantly by child sources, - * but we support older glib versions that do not have them. - */ - IOWatchPoll *iwp = io_watch_poll_from_source(source); - assert(iwp->src == NULL); + return G_SOURCE_CONTINUE; } static GSourceFuncs io_watch_poll_funcs = { .prepare = io_watch_poll_prepare, - .check = io_watch_poll_check, .dispatch = io_watch_poll_dispatch, - .finalize = io_watch_poll_finalize, }; GSource *io_add_watch_poll(Chardev *chr, @@ -115,7 +91,6 @@ GSource *io_add_watch_poll(Chardev *chr, iwp->ioc = ioc; iwp->fd_read = (GSourceFunc) fd_read; iwp->src = NULL; - iwp->context = context; name = g_strdup_printf("chardev-iowatch-%s", chr->label); g_source_set_name((GSource *)iwp, name); @@ -126,23 +101,10 @@ GSource *io_add_watch_poll(Chardev *chr, return (GSource *)iwp; } -static void io_remove_watch_poll(GSource *source) -{ - IOWatchPoll *iwp; - - iwp = io_watch_poll_from_source(source); - if (iwp->src) { - g_source_destroy(iwp->src); - g_source_unref(iwp->src); - iwp->src = NULL; - } - g_source_destroy(&iwp->parent); -} - void remove_fd_in_watch(Chardev *chr) { if (chr->gsource) { - io_remove_watch_poll(chr->gsource); + g_source_destroy(chr->gsource); chr->gsource = NULL; } } diff --git a/chardev/char-socket.c b/chardev/char-socket.c index 7cd0ae2824..a75b46d9fe 100644 --- a/chardev/char-socket.c +++ b/chardev/char-socket.c @@ -423,8 +423,12 @@ static void update_disconnected_filename(SocketChardev *s) Chardev *chr = CHARDEV(s); g_free(chr->filename); - chr->filename = SocketAddress_to_str("disconnected:", s->addr, - s->is_listen, s->is_telnet); + if (s->addr) { + chr->filename = SocketAddress_to_str("disconnected:", s->addr, + s->is_listen, s->is_telnet); + } else { + chr->filename = g_strdup("disconnected:socket"); + } } /* NB may be called even if tcp_chr_connect has not been diff --git a/chardev/char.c b/chardev/char.c index 76d866e6fe..e115166995 100644 --- a/chardev/char.c +++ b/chardev/char.c @@ -329,7 +329,8 @@ int qemu_chr_wait_connected(Chardev *chr, Error **errp) return 0; } -QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename) +QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename, + bool permit_mux_mon) { char host[65], port[33], width[8], height[8]; int pos; @@ -344,6 +345,10 @@ QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename) } if (strstart(filename, "mon:", &p)) { + if (!permit_mux_mon) { + error_report("mon: isn't supported in this context"); + return NULL; + } filename = p; qemu_opt_set(opts, "mux", "on", &error_abort); if (strcmp(filename, "stdio") == 0) { @@ -683,7 +688,8 @@ out: return chr; } -Chardev *qemu_chr_new_noreplay(const char *label, const char *filename) +Chardev *qemu_chr_new_noreplay(const char *label, const char *filename, + bool permit_mux_mon) { const char *p; Chardev *chr; @@ -694,25 +700,32 @@ Chardev *qemu_chr_new_noreplay(const char *label, const char *filename) return qemu_chr_find(p); } - opts = qemu_chr_parse_compat(label, filename); + opts = qemu_chr_parse_compat(label, filename, permit_mux_mon); if (!opts) return NULL; chr = qemu_chr_new_from_opts(opts, &err); - if (err) { + if (!chr) { error_report_err(err); + goto out; } - if (chr && qemu_opt_get_bool(opts, "mux", 0)) { + + if (qemu_opt_get_bool(opts, "mux", 0)) { + assert(permit_mux_mon); monitor_init(chr, MONITOR_USE_READLINE); } + +out: qemu_opts_del(opts); return chr; } -Chardev *qemu_chr_new(const char *label, const char *filename) +static Chardev *qemu_chr_new_permit_mux_mon(const char *label, + const char *filename, + bool permit_mux_mon) { Chardev *chr; - chr = qemu_chr_new_noreplay(label, filename); + chr = qemu_chr_new_noreplay(label, filename, permit_mux_mon); if (chr) { if (replay_mode != REPLAY_MODE_NONE) { qemu_chr_set_feature(chr, QEMU_CHAR_FEATURE_REPLAY); @@ -726,6 +739,16 @@ Chardev *qemu_chr_new(const char *label, const char *filename) return chr; } +Chardev *qemu_chr_new(const char *label, const char *filename) +{ + return qemu_chr_new_permit_mux_mon(label, filename, false); +} + +Chardev *qemu_chr_new_mux_mon(const char *label, const char *filename) +{ + return qemu_chr_new_permit_mux_mon(label, filename, true); +} + static int qmp_query_chardev_foreach(Object *obj, void *data) { Chardev *chr = CHARDEV(obj); @@ -2038,7 +2038,11 @@ int gdbserver_start(const char *device) sigaction(SIGINT, &act, NULL); } #endif - chr = qemu_chr_new_noreplay("gdb", device); + /* + * FIXME: it's a bit weird to allow using a mux chardev here + * and implicitly setup a monitor. We may want to break this. + */ + chr = qemu_chr_new_noreplay("gdb", device, true); if (!chr) return -1; } diff --git a/hw/char/xen_console.c b/hw/char/xen_console.c index 8b4b4bf523..44f7236382 100644 --- a/hw/char/xen_console.c +++ b/hw/char/xen_console.c @@ -207,7 +207,11 @@ static int con_init(struct XenDevice *xendev) } else { snprintf(label, sizeof(label), "xencons%d", con->xendev.dev); qemu_chr_fe_init(&con->chr, - qemu_chr_new(label, output), &error_abort); + /* + * FIXME: sure we want to support implicit + * muxed monitors here? + */ + qemu_chr_new_mux_mon(label, output), &error_abort); } xenstore_store_pv_console_info(con->xendev.dev, diff --git a/include/block/nbd.h b/include/block/nbd.h index 4638c839f5..6a5bfe5d55 100644 --- a/include/block/nbd.h +++ b/include/block/nbd.h @@ -135,7 +135,9 @@ typedef struct NBDExtent { #define NBD_FLAG_SEND_TRIM (1 << 5) /* Send TRIM (discard) */ #define NBD_FLAG_SEND_WRITE_ZEROES (1 << 6) /* Send WRITE_ZEROES */ #define NBD_FLAG_SEND_DF (1 << 7) /* Send DF (Do not Fragment) */ -#define NBD_FLAG_SEND_CACHE (1 << 8) /* Send CACHE (prefetch) */ +#define NBD_FLAG_CAN_MULTI_CONN (1 << 8) /* Multi-client cache consistent */ +#define NBD_FLAG_SEND_RESIZE (1 << 9) /* Send resize */ +#define NBD_FLAG_SEND_CACHE (1 << 10) /* Send CACHE (prefetch) */ /* New-style handshake (global) flags, sent from server to client, and control what will happen during handshake phase. */ @@ -308,8 +310,7 @@ void nbd_export_set_name(NBDExport *exp, const char *name); void nbd_export_set_description(NBDExport *exp, const char *description); void nbd_export_close_all(void); -void nbd_client_new(NBDExport *exp, - QIOChannelSocket *sioc, +void nbd_client_new(QIOChannelSocket *sioc, QCryptoTLSCreds *tlscreds, const char *tlsaclname, void (*close_fn)(NBDClient *, bool)); diff --git a/include/chardev/char-fe.h b/include/chardev/char-fe.h index c67271f1ba..46c997d352 100644 --- a/include/chardev/char-fe.h +++ b/include/chardev/char-fe.h @@ -20,7 +20,7 @@ struct CharBackend { }; /** - * @qemu_chr_fe_init: + * qemu_chr_fe_init: * * Initializes a front end for the given CharBackend and * Chardev. Call qemu_chr_fe_deinit() to remove the association and @@ -31,7 +31,7 @@ struct CharBackend { bool qemu_chr_fe_init(CharBackend *b, Chardev *s, Error **errp); /** - * @qemu_chr_fe_deinit: + * qemu_chr_fe_deinit: * @b: a CharBackend * @del: if true, delete the chardev backend * @@ -42,9 +42,9 @@ bool qemu_chr_fe_init(CharBackend *b, Chardev *s, Error **errp); void qemu_chr_fe_deinit(CharBackend *b, bool del); /** - * @qemu_chr_fe_get_driver: + * qemu_chr_fe_get_driver: * - * Returns the driver associated with a CharBackend or NULL if no + * Returns: the driver associated with a CharBackend or NULL if no * associated Chardev. * Note: avoid this function as the driver should never be accessed directly, * especially by the frontends that support chardevice hotswap. @@ -53,21 +53,21 @@ void qemu_chr_fe_deinit(CharBackend *b, bool del); Chardev *qemu_chr_fe_get_driver(CharBackend *be); /** - * @qemu_chr_fe_backend_connected: + * qemu_chr_fe_backend_connected: * - * Returns true if there is a chardevice associated with @be. + * Returns: true if there is a chardevice associated with @be. */ bool qemu_chr_fe_backend_connected(CharBackend *be); /** - * @qemu_chr_fe_backend_open: + * qemu_chr_fe_backend_open: * - * Returns true if chardevice associated with @be is open. + * Returns: true if chardevice associated with @be is open. */ bool qemu_chr_fe_backend_open(CharBackend *be); /** - * @qemu_chr_fe_set_handlers: + * qemu_chr_fe_set_handlers: * @b: a CharBackend * @fd_can_read: callback to get the amount of data the frontend may * receive @@ -95,7 +95,7 @@ void qemu_chr_fe_set_handlers(CharBackend *b, bool set_open); /** - * @qemu_chr_fe_take_focus: + * qemu_chr_fe_take_focus: * * Take the focus (if the front end is muxed). * @@ -104,14 +104,14 @@ void qemu_chr_fe_set_handlers(CharBackend *b, void qemu_chr_fe_take_focus(CharBackend *b); /** - * @qemu_chr_fe_accept_input: + * qemu_chr_fe_accept_input: * * Notify that the frontend is ready to receive data */ void qemu_chr_fe_accept_input(CharBackend *be); /** - * @qemu_chr_fe_disconnect: + * qemu_chr_fe_disconnect: * * Close a fd accepted by character backend. * Without associated Chardev, do nothing. @@ -119,7 +119,7 @@ void qemu_chr_fe_accept_input(CharBackend *be); void qemu_chr_fe_disconnect(CharBackend *be); /** - * @qemu_chr_fe_wait_connected: + * qemu_chr_fe_wait_connected: * * Wait for characted backend to be connected, return < 0 on error or * if no associated Chardev. @@ -127,19 +127,18 @@ void qemu_chr_fe_disconnect(CharBackend *be); int qemu_chr_fe_wait_connected(CharBackend *be, Error **errp); /** - * @qemu_chr_fe_set_echo: + * qemu_chr_fe_set_echo: + * @echo: true to enable echo, false to disable echo * * Ask the backend to override its normal echo setting. This only really * applies to the stdio backend and is used by the QMP server such that you * can see what you type if you try to type QMP commands. * Without associated Chardev, do nothing. - * - * @echo true to enable echo, false to disable echo */ void qemu_chr_fe_set_echo(CharBackend *be, bool echo); /** - * @qemu_chr_fe_set_open: + * qemu_chr_fe_set_open: * * Set character frontend open status. This is an indication that the * front end is ready (or not) to begin doing I/O. @@ -148,83 +147,77 @@ void qemu_chr_fe_set_echo(CharBackend *be, bool echo); void qemu_chr_fe_set_open(CharBackend *be, int fe_open); /** - * @qemu_chr_fe_printf: + * qemu_chr_fe_printf: + * @fmt: see #printf * * Write to a character backend using a printf style interface. This * function is thread-safe. It does nothing without associated * Chardev. - * - * @fmt see #printf */ void qemu_chr_fe_printf(CharBackend *be, const char *fmt, ...) GCC_FMT_ATTR(2, 3); /** - * @qemu_chr_fe_add_watch: + * qemu_chr_fe_add_watch: + * @cond: the condition to poll for + * @func: the function to call when the condition happens + * @user_data: the opaque pointer to pass to @func * * If the backend is connected, create and add a #GSource that fires * when the given condition (typically G_IO_OUT|G_IO_HUP or G_IO_HUP) * is active; return the #GSource's tag. If it is disconnected, * or without associated Chardev, return 0. * - * @cond the condition to poll for - * @func the function to call when the condition happens - * @user_data the opaque pointer to pass to @func - * * Returns: the source tag */ guint qemu_chr_fe_add_watch(CharBackend *be, GIOCondition cond, GIOFunc func, void *user_data); /** - * @qemu_chr_fe_write: + * qemu_chr_fe_write: + * @buf: the data + * @len: the number of bytes to send * * Write data to a character backend from the front end. This function * will send data from the front end to the back end. This function * is thread-safe. * - * @buf the data - * @len the number of bytes to send - * * Returns: the number of bytes consumed (0 if no associated Chardev) */ int qemu_chr_fe_write(CharBackend *be, const uint8_t *buf, int len); /** - * @qemu_chr_fe_write_all: + * qemu_chr_fe_write_all: + * @buf: the data + * @len: the number of bytes to send * * Write data to a character backend from the front end. This function will * send data from the front end to the back end. Unlike @qemu_chr_fe_write, * this function will block if the back end cannot consume all of the data * attempted to be written. This function is thread-safe. * - * @buf the data - * @len the number of bytes to send - * * Returns: the number of bytes consumed (0 if no associated Chardev) */ int qemu_chr_fe_write_all(CharBackend *be, const uint8_t *buf, int len); /** - * @qemu_chr_fe_read_all: + * qemu_chr_fe_read_all: + * @buf: the data buffer + * @len: the number of bytes to read * * Read data to a buffer from the back end. * - * @buf the data buffer - * @len the number of bytes to read - * * Returns: the number of bytes read (0 if no associated Chardev) */ int qemu_chr_fe_read_all(CharBackend *be, uint8_t *buf, int len); /** - * @qemu_chr_fe_ioctl: + * qemu_chr_fe_ioctl: + * @cmd: see CHR_IOCTL_* + * @arg: the data associated with @cmd * * Issue a device specific ioctl to a backend. This function is thread-safe. * - * @cmd see CHR_IOCTL_* - * @arg the data associated with @cmd - * * Returns: if @cmd is not supported by the backend or there is no * associated Chardev, -ENOTSUP, otherwise the return * value depends on the semantics of @cmd @@ -232,7 +225,7 @@ int qemu_chr_fe_read_all(CharBackend *be, uint8_t *buf, int len); int qemu_chr_fe_ioctl(CharBackend *be, int cmd, void *arg); /** - * @qemu_chr_fe_get_msgfd: + * qemu_chr_fe_get_msgfd: * * For backends capable of fd passing, return the latest file descriptor passed * by a client. @@ -245,7 +238,7 @@ int qemu_chr_fe_ioctl(CharBackend *be, int cmd, void *arg); int qemu_chr_fe_get_msgfd(CharBackend *be); /** - * @qemu_chr_fe_get_msgfds: + * qemu_chr_fe_get_msgfds: * * For backends capable of fd passing, return the number of file received * descriptors and fills the fds array up to num elements @@ -258,7 +251,7 @@ int qemu_chr_fe_get_msgfd(CharBackend *be); int qemu_chr_fe_get_msgfds(CharBackend *be, int *fds, int num); /** - * @qemu_chr_fe_set_msgfds: + * qemu_chr_fe_set_msgfds: * * For backends capable of fd passing, set an array of fds to be passed with * the next send operation. diff --git a/include/chardev/char.h b/include/chardev/char.h index 6f0576e214..7becd8c80c 100644 --- a/include/chardev/char.h +++ b/include/chardev/char.h @@ -68,12 +68,11 @@ struct Chardev { }; /** - * @qemu_chr_new_from_opts: + * qemu_chr_new_from_opts: + * @opts: see qemu-config.c for a list of valid options * * Create a new character backend from a QemuOpts list. * - * @opts see qemu-config.c for a list of valid options - * * Returns: on success: a new character backend * otherwise: NULL; @errp specifies the error * or left untouched in case of help option @@ -82,17 +81,16 @@ Chardev *qemu_chr_new_from_opts(QemuOpts *opts, Error **errp); /** - * @qemu_chr_parse_common: + * qemu_chr_parse_common: + * @opts: the options that still need parsing + * @backend: a new backend * * Parse the common options available to all character backends. - * - * @opts the options that still need parsing - * @backend a new backend */ void qemu_chr_parse_common(QemuOpts *opts, ChardevCommon *backend); /** - * @qemu_chr_parse_opts: + * qemu_chr_parse_opts: * * Parse the options to the ChardevBackend struct. * @@ -102,49 +100,61 @@ ChardevBackend *qemu_chr_parse_opts(QemuOpts *opts, Error **errp); /** - * @qemu_chr_new: + * qemu_chr_new: + * @label: the name of the backend + * @filename: the URI * * Create a new character backend from a URI. - * - * @label the name of the backend - * @filename the URI + * Do not implicitly initialize a monitor if the chardev is muxed. * * Returns: a new character backend */ Chardev *qemu_chr_new(const char *label, const char *filename); /** - * @qemu_chr_change: + * qemu_chr_new_mux_mon: + * @label: the name of the backend + * @filename: the URI * - * Change an existing character backend + * Create a new character backend from a URI. + * Implicitly initialize a monitor if the chardev is muxed. + * + * Returns: a new character backend + */ +Chardev *qemu_chr_new_mux_mon(const char *label, const char *filename); + +/** +* qemu_chr_change: +* @opts: the new backend options * - * @opts the new backend options + * Change an existing character backend */ void qemu_chr_change(QemuOpts *opts, Error **errp); /** - * @qemu_chr_cleanup: + * qemu_chr_cleanup: * * Delete all chardevs (when leaving qemu) */ void qemu_chr_cleanup(void); /** - * @qemu_chr_new_noreplay: + * qemu_chr_new_noreplay: + * @label: the name of the backend + * @filename: the URI + * @permit_mux_mon: if chardev is muxed, initialize a monitor * * Create a new character backend from a URI. * Character device communications are not written * into the replay log. * - * @label the name of the backend - * @filename the URI - * * Returns: a new character backend */ -Chardev *qemu_chr_new_noreplay(const char *label, const char *filename); +Chardev *qemu_chr_new_noreplay(const char *label, const char *filename, + bool permit_mux_mon); /** - * @qemu_chr_be_can_write: + * qemu_chr_be_can_write: * * Determine how much data the front end can currently accept. This function * returns the number of bytes the front end can accept. If it returns 0, the @@ -156,43 +166,39 @@ Chardev *qemu_chr_new_noreplay(const char *label, const char *filename); int qemu_chr_be_can_write(Chardev *s); /** - * @qemu_chr_be_write: + * qemu_chr_be_write: + * @buf: a buffer to receive data from the front end + * @len: the number of bytes to receive from the front end * * Write data from the back end to the front end. Before issuing this call, * the caller should call @qemu_chr_be_can_write to determine how much data * the front end can currently accept. - * - * @buf a buffer to receive data from the front end - * @len the number of bytes to receive from the front end */ void qemu_chr_be_write(Chardev *s, uint8_t *buf, int len); /** - * @qemu_chr_be_write_impl: + * qemu_chr_be_write_impl: + * @buf: a buffer to receive data from the front end + * @len: the number of bytes to receive from the front end * * Implementation of back end writing. Used by replay module. - * - * @buf a buffer to receive data from the front end - * @len the number of bytes to receive from the front end */ void qemu_chr_be_write_impl(Chardev *s, uint8_t *buf, int len); /** - * @qemu_chr_be_update_read_handlers: + * qemu_chr_be_update_read_handlers: + * @context: the gcontext that will be used to attach the watch sources * * Invoked when frontend read handlers are setup - * - * @context the gcontext that will be used to attach the watch sources */ void qemu_chr_be_update_read_handlers(Chardev *s, GMainContext *context); /** - * @qemu_chr_be_event: + * qemu_chr_be_event: + * @event: the event to send * * Send an event from the back end to the front end. - * - * @event the event to send */ void qemu_chr_be_event(Chardev *s, int event); @@ -203,7 +209,8 @@ bool qemu_chr_has_feature(Chardev *chr, ChardevFeature feature); void qemu_chr_set_feature(Chardev *chr, ChardevFeature feature); -QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename); +QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename, + bool permit_mux_mon); int qemu_chr_write(Chardev *s, const uint8_t *buf, int len, bool write_all); #define qemu_chr_write_all(s, buf, len) qemu_chr_write(s, buf, len, true) int qemu_chr_wait_connected(Chardev *chr, Error **errp); diff --git a/nbd/client.c b/nbd/client.c index 40b74d9761..b4d457a19a 100644 --- a/nbd/client.c +++ b/nbd/client.c @@ -117,10 +117,10 @@ static int nbd_receive_option_reply(QIOChannel *ioc, uint32_t opt, nbd_send_opt_abort(ioc); return -1; } - be64_to_cpus(&reply->magic); - be32_to_cpus(&reply->option); - be32_to_cpus(&reply->type); - be32_to_cpus(&reply->length); + reply->magic = be64_to_cpu(reply->magic); + reply->option = be32_to_cpu(reply->option); + reply->type = be32_to_cpu(reply->type); + reply->length = be32_to_cpu(reply->length); trace_nbd_receive_option_reply(reply->option, nbd_opt_lookup(reply->option), reply->type, nbd_rep_lookup(reply->type), @@ -396,7 +396,7 @@ static int nbd_opt_go(QIOChannel *ioc, const char *wantname, return -1; } len -= sizeof(type); - be16_to_cpus(&type); + type = be16_to_cpu(type); switch (type) { case NBD_INFO_EXPORT: if (len != sizeof(info->size) + sizeof(info->flags)) { @@ -410,13 +410,13 @@ static int nbd_opt_go(QIOChannel *ioc, const char *wantname, nbd_send_opt_abort(ioc); return -1; } - be64_to_cpus(&info->size); + info->size = be64_to_cpu(info->size); if (nbd_read(ioc, &info->flags, sizeof(info->flags), errp) < 0) { error_prepend(errp, "failed to read info flags: "); nbd_send_opt_abort(ioc); return -1; } - be16_to_cpus(&info->flags); + info->flags = be16_to_cpu(info->flags); trace_nbd_receive_negotiate_size_flags(info->size, info->flags); break; @@ -433,7 +433,7 @@ static int nbd_opt_go(QIOChannel *ioc, const char *wantname, nbd_send_opt_abort(ioc); return -1; } - be32_to_cpus(&info->min_block); + info->min_block = be32_to_cpu(info->min_block); if (!is_power_of_2(info->min_block)) { error_setg(errp, "server minimum block size %" PRIu32 " is not a power of two", info->min_block); @@ -447,7 +447,7 @@ static int nbd_opt_go(QIOChannel *ioc, const char *wantname, nbd_send_opt_abort(ioc); return -1; } - be32_to_cpus(&info->opt_block); + info->opt_block = be32_to_cpu(info->opt_block); if (!is_power_of_2(info->opt_block) || info->opt_block < info->min_block) { error_setg(errp, "server preferred block size %" PRIu32 @@ -461,7 +461,7 @@ static int nbd_opt_go(QIOChannel *ioc, const char *wantname, nbd_send_opt_abort(ioc); return -1; } - be32_to_cpus(&info->max_block); + info->max_block = be32_to_cpu(info->max_block); if (info->max_block < info->min_block) { error_setg(errp, "server maximum block size %" PRIu32 " is not valid", info->max_block); @@ -668,7 +668,7 @@ static int nbd_negotiate_simple_meta_context(QIOChannel *ioc, if (nbd_read(ioc, &received_id, sizeof(received_id), errp) < 0) { return -1; } - be32_to_cpus(&received_id); + received_id = be32_to_cpu(received_id); reply.length -= sizeof(received_id); name = g_malloc(reply.length + 1); @@ -872,13 +872,13 @@ int nbd_receive_negotiate(QIOChannel *ioc, const char *name, error_prepend(errp, "Failed to read export length: "); goto fail; } - be64_to_cpus(&info->size); + info->size = be64_to_cpu(info->size); if (nbd_read(ioc, &info->flags, sizeof(info->flags), errp) < 0) { error_prepend(errp, "Failed to read export flags: "); goto fail; } - be16_to_cpus(&info->flags); + info->flags = be16_to_cpu(info->flags); } else if (magic == NBD_CLIENT_MAGIC) { uint32_t oldflags; @@ -895,13 +895,13 @@ int nbd_receive_negotiate(QIOChannel *ioc, const char *name, error_prepend(errp, "Failed to read export length: "); goto fail; } - be64_to_cpus(&info->size); + info->size = be64_to_cpu(info->size); if (nbd_read(ioc, &oldflags, sizeof(oldflags), errp) < 0) { error_prepend(errp, "Failed to read export flags: "); goto fail; } - be32_to_cpus(&oldflags); + oldflags = be32_to_cpu(oldflags); if (oldflags & ~0xffff) { error_setg(errp, "Unexpected export flags %0x" PRIx32, oldflags); goto fail; @@ -1080,8 +1080,8 @@ static int nbd_receive_simple_reply(QIOChannel *ioc, NBDSimpleReply *reply, return ret; } - be32_to_cpus(&reply->error); - be64_to_cpus(&reply->handle); + reply->error = be32_to_cpu(reply->error); + reply->handle = be64_to_cpu(reply->handle); return 0; } @@ -1105,10 +1105,10 @@ static int nbd_receive_structured_reply_chunk(QIOChannel *ioc, return ret; } - be16_to_cpus(&chunk->flags); - be16_to_cpus(&chunk->type); - be64_to_cpus(&chunk->handle); - be32_to_cpus(&chunk->length); + chunk->flags = be16_to_cpu(chunk->flags); + chunk->type = be16_to_cpu(chunk->type); + chunk->handle = be64_to_cpu(chunk->handle); + chunk->length = be32_to_cpu(chunk->length); return 0; } @@ -1128,7 +1128,7 @@ int nbd_receive_reply(QIOChannel *ioc, NBDReply *reply, Error **errp) return ret; } - be32_to_cpus(&reply->magic); + reply->magic = be32_to_cpu(reply->magic); switch (reply->magic) { case NBD_SIMPLE_REPLY_MAGIC: diff --git a/nbd/server.c b/nbd/server.c index c3dd402b45..a1eda0114f 100644 --- a/nbd/server.c +++ b/nbd/server.c @@ -333,7 +333,7 @@ static int nbd_opt_read_name(NBDClient *client, char *name, uint32_t *length, if (ret <= 0) { return ret; } - cpu_to_be32s(&len); + len = cpu_to_be32(len); if (len > NBD_MAX_NAME_SIZE) { return nbd_opt_invalid(client, errp, @@ -486,7 +486,7 @@ static int nbd_negotiate_send_info(NBDClient *client, if (rc < 0) { return rc; } - cpu_to_be16s(&info); + info = cpu_to_be16(info); if (nbd_write(client->ioc, &info, sizeof(info), errp) < 0) { return -EIO; } @@ -551,14 +551,14 @@ static int nbd_negotiate_handle_info(NBDClient *client, uint16_t myflags, if (rc <= 0) { return rc; } - be16_to_cpus(&requests); + requests = be16_to_cpu(requests); trace_nbd_negotiate_handle_info_requests(requests); while (requests--) { rc = nbd_opt_read(client, &request, sizeof(request), errp); if (rc <= 0) { return rc; } - be16_to_cpus(&request); + request = be16_to_cpu(request); trace_nbd_negotiate_handle_info_request(request, nbd_info_lookup(request)); /* We care about NBD_INFO_NAME and NBD_INFO_BLOCK_SIZE; @@ -618,9 +618,9 @@ static int nbd_negotiate_handle_info(NBDClient *client, uint16_t myflags, /* maximum - At most 32M, but smaller as appropriate. */ sizes[2] = MIN(blk_get_max_transfer(exp->blk), NBD_MAX_BUFFER_SIZE); trace_nbd_negotiate_handle_info_block_size(sizes[0], sizes[1], sizes[2]); - cpu_to_be32s(&sizes[0]); - cpu_to_be32s(&sizes[1]); - cpu_to_be32s(&sizes[2]); + sizes[0] = cpu_to_be32(sizes[0]); + sizes[1] = cpu_to_be32(sizes[1]); + sizes[2] = cpu_to_be32(sizes[2]); rc = nbd_negotiate_send_info(client, NBD_INFO_BLOCK_SIZE, sizeof(sizes), sizes, errp); if (rc < 0) { @@ -904,7 +904,7 @@ static int nbd_negotiate_meta_query(NBDClient *client, if (ret <= 0) { return ret; } - cpu_to_be32s(&len); + len = cpu_to_be32(len); if (len < ns_len) { trace_nbd_negotiate_meta_query_skip("length too short"); @@ -971,7 +971,7 @@ static int nbd_negotiate_meta_queries(NBDClient *client, if (ret <= 0) { return ret; } - cpu_to_be32s(&nb_queries); + nb_queries = cpu_to_be32(nb_queries); trace_nbd_negotiate_meta_context(nbd_opt_lookup(client->opt), export_name, nb_queries); @@ -1049,7 +1049,7 @@ static int nbd_negotiate_options(NBDClient *client, uint16_t myflags, error_prepend(errp, "read failed: "); return -EIO; } - be32_to_cpus(&flags); + flags = be32_to_cpu(flags); trace_nbd_negotiate_options_flags(flags); if (flags & NBD_FLAG_C_FIXED_NEWSTYLE) { fixedNewstyle = true; @@ -1253,7 +1253,6 @@ static coroutine_fn int nbd_negotiate(NBDClient *client, Error **errp) const uint16_t myflags = (NBD_FLAG_HAS_FLAGS | NBD_FLAG_SEND_TRIM | NBD_FLAG_SEND_FLUSH | NBD_FLAG_SEND_FUA | NBD_FLAG_SEND_WRITE_ZEROES | NBD_FLAG_SEND_CACHE); - bool oldStyle; /* Old style negotiation header, no room for options [ 0 .. 7] passwd ("NBDMAGIC") @@ -1274,33 +1273,19 @@ static coroutine_fn int nbd_negotiate(NBDClient *client, Error **errp) trace_nbd_negotiate_begin(); memcpy(buf, "NBDMAGIC", 8); - oldStyle = client->exp != NULL && !client->tlscreds; - if (oldStyle) { - trace_nbd_negotiate_old_style(client->exp->size, - client->exp->nbdflags | myflags); - stq_be_p(buf + 8, NBD_CLIENT_MAGIC); - stq_be_p(buf + 16, client->exp->size); - stl_be_p(buf + 24, client->exp->nbdflags | myflags); + stq_be_p(buf + 8, NBD_OPTS_MAGIC); + stw_be_p(buf + 16, NBD_FLAG_FIXED_NEWSTYLE | NBD_FLAG_NO_ZEROES); - if (nbd_write(client->ioc, buf, sizeof(buf), errp) < 0) { - error_prepend(errp, "write failed: "); - return -EINVAL; - } - } else { - stq_be_p(buf + 8, NBD_OPTS_MAGIC); - stw_be_p(buf + 16, NBD_FLAG_FIXED_NEWSTYLE | NBD_FLAG_NO_ZEROES); - - if (nbd_write(client->ioc, buf, 18, errp) < 0) { - error_prepend(errp, "write failed: "); - return -EINVAL; - } - ret = nbd_negotiate_options(client, myflags, errp); - if (ret != 0) { - if (ret < 0) { - error_prepend(errp, "option negotiation failed: "); - } - return ret; + if (nbd_write(client->ioc, buf, 18, errp) < 0) { + error_prepend(errp, "write failed: "); + return -EINVAL; + } + ret = nbd_negotiate_options(client, myflags, errp); + if (ret != 0) { + if (ret < 0) { + error_prepend(errp, "option negotiation failed: "); } + return ret; } assert(!client->optlen); @@ -1900,8 +1885,8 @@ static int blockstatus_to_extents(BlockDriverState *bs, uint64_t offset, extents_end = extent + 1; for (extent = extents; extent < extents_end; extent++) { - cpu_to_be32s(&extent->flags); - cpu_to_be32s(&extent->length); + extent->flags = cpu_to_be32(extent->flags); + extent->length = cpu_to_be32(extent->length); } *bytes -= remaining_bytes; @@ -2177,7 +2162,8 @@ static coroutine_fn int nbd_do_cmd_read(NBDClient *client, NBDRequest *request, } if (client->structured_reply && !(request->flags & NBD_CMD_FLAG_DF) && - request->len) { + request->len && request->type != NBD_CMD_CACHE) + { return nbd_co_send_sparse_read(client, request->handle, request->from, data, request->len, errp); } @@ -2395,13 +2381,8 @@ static void nbd_client_receive_next_request(NBDClient *client) static coroutine_fn void nbd_co_client_start(void *opaque) { NBDClient *client = opaque; - NBDExport *exp = client->exp; Error *local_err = NULL; - if (exp) { - nbd_export_get(exp); - QTAILQ_INSERT_TAIL(&exp->clients, client, next); - } qemu_co_mutex_init(&client->send_lock); if (nbd_negotiate(client, &local_err)) { @@ -2416,13 +2397,11 @@ static coroutine_fn void nbd_co_client_start(void *opaque) } /* - * Create a new client listener on the given export @exp, using the - * given channel @sioc. Begin servicing it in a coroutine. When the - * connection closes, call @close_fn with an indication of whether the - * client completed negotiation. + * Create a new client listener using the given channel @sioc. + * Begin servicing it in a coroutine. When the connection closes, call + * @close_fn with an indication of whether the client completed negotiation. */ -void nbd_client_new(NBDExport *exp, - QIOChannelSocket *sioc, +void nbd_client_new(QIOChannelSocket *sioc, QCryptoTLSCreds *tlscreds, const char *tlsaclname, void (*close_fn)(NBDClient *, bool)) @@ -2432,7 +2411,6 @@ void nbd_client_new(NBDExport *exp, client = g_new0(NBDClient, 1); client->refcount = 1; - client->exp = exp; client->tlscreds = tlscreds; if (tlscreds) { object_ref(OBJECT(client->tlscreds)); diff --git a/net/slirp.c b/net/slirp.c index c93b64dd91..99884de204 100644 --- a/net/slirp.c +++ b/net/slirp.c @@ -764,7 +764,11 @@ static int slirp_guestfwd(SlirpState *s, const char *config_str, Error **errp) } } else { Error *err = NULL; - Chardev *chr = qemu_chr_new(buf, p); + /* + * FIXME: sure we want to support implicit + * muxed monitors here? + */ + Chardev *chr = qemu_chr_new_mux_mon(buf, p); if (!chr) { error_setg(errp, "Could not open guest forwarding device '%s'", diff --git a/qemu-nbd.c b/qemu-nbd.c index 51b9d38c72..e76fe3082a 100644 --- a/qemu-nbd.c +++ b/qemu-nbd.c @@ -56,7 +56,6 @@ #define MBR_SIZE 512 static NBDExport *exp; -static bool newproto; static int verbose; static char *srcpath; static SocketAddress *saddr; @@ -84,8 +83,8 @@ static void usage(const char *name) " -e, --shared=NUM device can be shared by NUM clients (default '1')\n" " -t, --persistent don't exit on the last connection\n" " -v, --verbose display extra debugging information\n" -" -x, --export-name=NAME expose export by name\n" -" -D, --description=TEXT with -x, also export a human-readable description\n" +" -x, --export-name=NAME expose export by name (default is empty string)\n" +" -D, --description=TEXT export a human-readable description\n" "\n" "Exposing part of the image:\n" " -o, --offset=OFFSET offset into the image\n" @@ -94,6 +93,7 @@ static void usage(const char *name) "General purpose options:\n" " --object type,id=ID,... define an object such as 'secret' for providing\n" " passwords and/or encryption keys\n" +" --tls-creds=ID use id of an earlier --object to provide TLS\n" " -T, --trace [[enable=]<pattern>][,events=<file>][,file=<file>]\n" " specify tracing options\n" " --fork fork off the server process and exit the parent\n" @@ -354,8 +354,7 @@ static void nbd_accept(QIONetListener *listener, QIOChannelSocket *cioc, nb_fds++; nbd_update_server_watch(); - nbd_client_new(newproto ? NULL : exp, cioc, - tlscreds, NULL, nbd_client_closed); + nbd_client_new(cioc, tlscreds, NULL, nbd_client_closed); } static void nbd_update_server_watch(void) @@ -549,7 +548,7 @@ int main(int argc, char **argv) Error *local_err = NULL; BlockdevDetectZeroesOptions detect_zeroes = BLOCKDEV_DETECT_ZEROES_OPTIONS_OFF; QDict *options = NULL; - const char *export_name = NULL; + const char *export_name = ""; /* Default export name */ const char *export_description = NULL; const char *tlscredsid = NULL; bool imageOpts = false; @@ -808,11 +807,6 @@ int main(int argc, char **argv) error_report("TLS is not supported with a host device"); exit(EXIT_FAILURE); } - if (!export_name) { - /* Set the default NBD protocol export name, since - * we *must* use new style protocol for TLS */ - export_name = ""; - } tlscreds = nbd_get_tls_creds(tlscredsid, &local_err); if (local_err) { error_report("Failed to get TLS creds %s", @@ -1013,14 +1007,8 @@ int main(int argc, char **argv) error_report_err(local_err); exit(EXIT_FAILURE); } - if (export_name) { - nbd_export_set_name(exp, export_name); - nbd_export_set_description(exp, export_description); - newproto = true; - } else if (export_description) { - error_report("Export description requires an export name"); - exit(EXIT_FAILURE); - } + nbd_export_set_name(exp, export_name); + nbd_export_set_description(exp, export_description); if (device) { int ret; diff --git a/scripts/device-crash-test b/scripts/device-crash-test index 7045594bd4..930200b034 100755 --- a/scripts/device-crash-test +++ b/scripts/device-crash-test @@ -35,7 +35,6 @@ import random import argparse from itertools import chain -sys.path.append(os.path.join(os.path.dirname(__file__), '..', 'scripts')) from qemu import QEMUMachine logger = logging.getLogger('device-crash-test') @@ -99,7 +98,6 @@ ERROR_WHITELIST = [ {'device':'isa-ipmi-bt', 'expected':True}, # IPMI device requires a bmc attribute to be set {'device':'isa-ipmi-kcs', 'expected':True}, # IPMI device requires a bmc attribute to be set {'device':'isa-parallel', 'expected':True}, # Can't create serial device, empty char device - {'device':'isa-serial', 'expected':True}, # Can't create serial device, empty char device {'device':'ivshmem', 'expected':True}, # You must specify either 'shm' or 'chardev' {'device':'ivshmem-doorbell', 'expected':True}, # You must specify a 'chardev' {'device':'ivshmem-plain', 'expected':True}, # You must specify a 'memdev' @@ -110,9 +108,6 @@ ERROR_WHITELIST = [ {'device':'pc-dimm', 'expected':True}, # 'memdev' property is not set {'device':'pci-bridge', 'expected':True}, # Bridge chassis not specified. Each bridge is required to be assigned a unique chassis id > 0. {'device':'pci-bridge-seat', 'expected':True}, # Bridge chassis not specified. Each bridge is required to be assigned a unique chassis id > 0. - {'device':'pci-serial', 'expected':True}, # Can't create serial device, empty char device - {'device':'pci-serial-2x', 'expected':True}, # Can't create serial device, empty char device - {'device':'pci-serial-4x', 'expected':True}, # Can't create serial device, empty char device {'device':'pxa2xx-dma', 'expected':True}, # channels value invalid {'device':'pxb', 'expected':True}, # Bridge chassis not specified. Each bridge is required to be assigned a unique chassis id > 0. {'device':'scsi-block', 'expected':True}, # drive property not set @@ -218,7 +213,6 @@ ERROR_WHITELIST = [ {'exitcode':-6, 'log':r"Object .* is not an instance of type generic-pc-machine", 'loglevel':logging.ERROR}, {'exitcode':-6, 'log':r"Object .* is not an instance of type e500-ccsr", 'loglevel':logging.ERROR}, {'exitcode':-6, 'log':r"vmstate_register_with_alias_id: Assertion `!se->compat \|\| se->instance_id == 0' failed", 'loglevel':logging.ERROR}, - {'exitcode':-11, 'device':'isa-serial', 'loglevel':logging.ERROR, 'expected':True}, # everything else (including SIGABRT and SIGSEGV) will be a fatal error: {'exitcode':None, 'fatal':True, 'loglevel':logging.FATAL}, diff --git a/tests/docker/docker.py b/tests/docker/docker.py index d3006d4dae..44d5f7493b 100755 --- a/tests/docker/docker.py +++ b/tests/docker/docker.py @@ -14,14 +14,12 @@ from __future__ import print_function import os import sys -sys.path.append(os.path.join(os.path.dirname(__file__), - '..', '..', 'scripts')) -import argparse import subprocess import json import hashlib import atexit import uuid +import argparse import tempfile import re import signal diff --git a/tests/migration/guestperf/shell.py b/tests/migration/guestperf/shell.py index a6b8cec1e0..61d2abbaad 100644 --- a/tests/migration/guestperf/shell.py +++ b/tests/migration/guestperf/shell.py @@ -19,14 +19,12 @@ from __future__ import print_function # -import os -import os.path -import sys -sys.path.append(os.path.join(os.path.dirname(__file__), - '..', '..', '..', 'scripts')) import argparse import fnmatch +import os +import os.path import platform +import sys import logging from guestperf.hardware import Hardware @@ -2310,7 +2310,7 @@ static void monitor_parse(const char *optarg, const char *mode, bool pretty) } else { snprintf(label, sizeof(label), "compat_monitor%d", monitor_device_index); - opts = qemu_chr_parse_compat(label, optarg); + opts = qemu_chr_parse_compat(label, optarg, true); if (!opts) { error_report("parse error: %s", optarg); exit(1); @@ -2382,7 +2382,7 @@ static int serial_parse(const char *devname) snprintf(label, sizeof(label), "serial%d", index); serial_hds = g_renew(Chardev *, serial_hds, index + 1); - serial_hds[index] = qemu_chr_new(label, devname); + serial_hds[index] = qemu_chr_new_mux_mon(label, devname); if (!serial_hds[index]) { error_report("could not connect serial device" " to character backend '%s'", devname); @@ -2418,7 +2418,7 @@ static int parallel_parse(const char *devname) exit(1); } snprintf(label, sizeof(label), "parallel%d", index); - parallel_hds[index] = qemu_chr_new(label, devname); + parallel_hds[index] = qemu_chr_new_mux_mon(label, devname); if (!parallel_hds[index]) { error_report("could not connect parallel device" " to character backend '%s'", devname); @@ -2449,7 +2449,7 @@ static int virtcon_parse(const char *devname) qemu_opt_set(dev_opts, "driver", "virtconsole", &error_abort); snprintf(label, sizeof(label), "virtcon%d", index); - virtcon_hds[index] = qemu_chr_new(label, devname); + virtcon_hds[index] = qemu_chr_new_mux_mon(label, devname); if (!virtcon_hds[index]) { error_report("could not connect virtio console" " to character backend '%s'", devname); @@ -2465,7 +2465,7 @@ static int debugcon_parse(const char *devname) { QemuOpts *opts; - if (!qemu_chr_new("debugcon", devname)) { + if (!qemu_chr_new_mux_mon("debugcon", devname)) { exit(1); } opts = qemu_opts_create(qemu_find_opts("device"), "debugcon", 1, NULL); |