[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PULL 13/69] chardev: allow telnet gsource to switch gconte
From: |
Paolo Bonzini |
Subject: |
[Qemu-devel] [PULL 13/69] chardev: allow telnet gsource to switch gcontext |
Date: |
Tue, 13 Mar 2018 23:46:23 +0100 |
From: Peter Xu <address@hidden>
It was originally created by qio_channel_add_watch() so it's always
assigning the task to main context. Now we use the new API called
qio_channel_add_watch_source() so that we get the GSource handle rather
than the tag ID.
Meanwhile, caching the gsource and TCPChardevTelnetInit (which holds the
handshake data) in SocketChardev.telnet_source so that we can also do
dynamic context switch when update read handlers.
Signed-off-by: Peter Xu <address@hidden>
Message-Id: <address@hidden>
Acked-by: Stefan Hajnoczi <address@hidden>
Reviewed-by: Daniel P. Berrangé <address@hidden>
Signed-off-by: Paolo Bonzini <address@hidden>
---
chardev/char-socket.c | 67 +++++++++++++++++++++++++++++++++++++++------------
1 file changed, 51 insertions(+), 16 deletions(-)
diff --git a/chardev/char-socket.c b/chardev/char-socket.c
index 2475e1d52f..82c7d7a323 100644
--- a/chardev/char-socket.c
+++ b/chardev/char-socket.c
@@ -40,6 +40,11 @@
#define TCP_MAX_FDS 16
+typedef struct {
+ char buf[21];
+ size_t buflen;
+} TCPChardevTelnetInit;
+
typedef struct {
Chardev parent;
QIOChannel *ioc; /* Client I/O channel */
@@ -60,6 +65,8 @@ typedef struct {
bool is_listen;
bool is_telnet;
bool is_tn3270;
+ GSource *telnet_source;
+ TCPChardevTelnetInit *telnet_init;
GSource *reconnect_timer;
int64_t reconnect_time;
@@ -70,6 +77,7 @@ typedef struct {
OBJECT_CHECK(SocketChardev, (obj), TYPE_CHARDEV_SOCKET)
static gboolean socket_reconnect_timeout(gpointer opaque);
+static void tcp_chr_telnet_init(Chardev *chr);
static void tcp_chr_reconn_timer_cancel(SocketChardev *s)
{
@@ -556,6 +564,15 @@ static void tcp_chr_connect(void *opaque)
qemu_chr_be_event(chr, CHR_EVENT_OPENED);
}
+static void tcp_chr_telnet_destroy(SocketChardev *s)
+{
+ if (s->telnet_source) {
+ g_source_destroy(s->telnet_source);
+ g_source_unref(s->telnet_source);
+ s->telnet_source = NULL;
+ }
+}
+
static void tcp_chr_update_read_handler(Chardev *chr)
{
SocketChardev *s = SOCKET_CHARDEV(chr);
@@ -570,6 +587,10 @@ static void tcp_chr_update_read_handler(Chardev *chr)
chr, NULL, chr->gcontext);
}
+ if (s->telnet_source) {
+ tcp_chr_telnet_init(CHARDEV(s));
+ }
+
if (!s->connected) {
return;
}
@@ -583,32 +604,30 @@ static void tcp_chr_update_read_handler(Chardev *chr)
}
}
-typedef struct {
- Chardev *chr;
- char buf[21];
- size_t buflen;
-} TCPChardevTelnetInit;
-
static gboolean tcp_chr_telnet_init_io(QIOChannel *ioc,
GIOCondition cond G_GNUC_UNUSED,
gpointer user_data)
{
- TCPChardevTelnetInit *init = user_data;
+ SocketChardev *s = user_data;
+ Chardev *chr = CHARDEV(s);
+ TCPChardevTelnetInit *init = s->telnet_init;
ssize_t ret;
+ assert(init);
+
ret = qio_channel_write(ioc, init->buf, init->buflen, NULL);
if (ret < 0) {
if (ret == QIO_CHANNEL_ERR_BLOCK) {
ret = 0;
} else {
- tcp_chr_disconnect(init->chr);
+ tcp_chr_disconnect(chr);
goto end;
}
}
init->buflen -= ret;
if (init->buflen == 0) {
- tcp_chr_connect(init->chr);
+ tcp_chr_connect(chr);
goto end;
}
@@ -617,16 +636,30 @@ static gboolean tcp_chr_telnet_init_io(QIOChannel *ioc,
return G_SOURCE_CONTINUE;
end:
- g_free(init);
+ g_free(s->telnet_init);
+ s->telnet_init = NULL;
+ g_source_unref(s->telnet_source);
+ s->telnet_source = NULL;
return G_SOURCE_REMOVE;
}
static void tcp_chr_telnet_init(Chardev *chr)
{
SocketChardev *s = SOCKET_CHARDEV(chr);
- TCPChardevTelnetInit *init = g_new0(TCPChardevTelnetInit, 1);
+ TCPChardevTelnetInit *init;
size_t n = 0;
+ /* Destroy existing task */
+ tcp_chr_telnet_destroy(s);
+
+ if (s->telnet_init) {
+ /* We are possibly during a handshake already */
+ goto cont;
+ }
+
+ s->telnet_init = g_new0(TCPChardevTelnetInit, 1);
+ init = s->telnet_init;
+
#define IACSET(x, a, b, c) \
do { \
x[n++] = a; \
@@ -634,7 +667,6 @@ static void tcp_chr_telnet_init(Chardev *chr)
x[n++] = c; \
} while (0)
- init->chr = chr;
if (!s->is_tn3270) {
init->buflen = 12;
/* Prep the telnet negotion to put telnet in binary,
@@ -657,10 +689,11 @@ static void tcp_chr_telnet_init(Chardev *chr)
#undef IACSET
- qio_channel_add_watch(
- s->ioc, G_IO_OUT,
- tcp_chr_telnet_init_io,
- init, NULL);
+cont:
+ s->telnet_source = qio_channel_add_watch_source(s->ioc, G_IO_OUT,
+ tcp_chr_telnet_init_io,
+ s, NULL,
+ chr->gcontext);
}
@@ -835,6 +868,8 @@ static void char_socket_finalize(Object *obj)
tcp_chr_free_connection(chr);
tcp_chr_reconn_timer_cancel(s);
qapi_free_SocketAddress(s->addr);
+ tcp_chr_telnet_destroy(s);
+ g_free(s->telnet_init);
if (s->listener) {
qio_net_listener_set_client_func_full(s->listener, NULL, NULL,
NULL, chr->gcontext);
--
2.14.3
- [Qemu-devel] [PULL 01/69] qom: introduce object_class_get_list_sorted, (continued)
- [Qemu-devel] [PULL 01/69] qom: introduce object_class_get_list_sorted, Paolo Bonzini, 2018/03/13
- [Qemu-devel] [PULL 03/69] q35: change default NIC to e1000e, Paolo Bonzini, 2018/03/13
- [Qemu-devel] [PULL 04/69] scsi-disk.c: consider bl->max_transfer in INQUIRY emulation, Paolo Bonzini, 2018/03/13
- [Qemu-devel] [PULL 06/69] qemu-doc: Add the paragraph about the -no-frame deprecation again, Paolo Bonzini, 2018/03/13
- [Qemu-devel] [PULL 07/69] build-sys: make help could have 'modules' target, Paolo Bonzini, 2018/03/13
- [Qemu-devel] [PULL 02/69] net: allow using any PCI NICs in -net or -nic, Paolo Bonzini, 2018/03/13
- [Qemu-devel] [PULL 09/69] checkpatch: Exempt long URLs, Paolo Bonzini, 2018/03/13
- [Qemu-devel] [PULL 11/69] chardev: fix handling of EAGAIN for TCP chardev, Paolo Bonzini, 2018/03/13
- [Qemu-devel] [PULL 10/69] vl: export machine_init_done, Paolo Bonzini, 2018/03/13
- [Qemu-devel] [PULL 08/69] hw: Do not include "sysemu/block-backend.h" if it is not necessary, Paolo Bonzini, 2018/03/13
- [Qemu-devel] [PULL 13/69] chardev: allow telnet gsource to switch gcontext,
Paolo Bonzini <=
- [Qemu-devel] [PULL 15/69] chardev: use chardev's gcontext for async connect, Paolo Bonzini, 2018/03/13
- [Qemu-devel] [PULL 12/69] chardev: update net listener gcontext, Paolo Bonzini, 2018/03/13
- [Qemu-devel] [PULL 14/69] chardev: introduce chr_machine_done hook, Paolo Bonzini, 2018/03/13
- [Qemu-devel] [PULL 16/69] chardev: tcp: postpone async connection setup, Paolo Bonzini, 2018/03/13
- [Qemu-devel] [PULL 19/69] hw/i386: make IOMMUs configurable via default-configs/, Paolo Bonzini, 2018/03/13
- [Qemu-devel] [PULL 18/69] scsi: support NDOB (no data-out buffer) for WRITE SAME commands, Paolo Bonzini, 2018/03/13
- [Qemu-devel] [PULL 22/69] rcutorture: remove synchronize_rcu from readers, Paolo Bonzini, 2018/03/13
- [Qemu-devel] [PULL 21/69] hw/mips/jazz: Fix implicit creation of "-drive if=scsi" devices, Paolo Bonzini, 2018/03/13
- [Qemu-devel] [PULL 17/69] chardev: tcp: let TLS run on chardev context, Paolo Bonzini, 2018/03/13
- [Qemu-devel] [PULL 20/69] Polish the version strings containing the package version, Paolo Bonzini, 2018/03/13