From: Ian Molton <ian.molton@collabora.co.uk>
To: Anthony Liguori <anthony@codemonkey.ws>
Cc: "qemu-devel@nongnu.org" <qemu-devel@nongnu.org>
Subject: [Qemu-devel] [PATCH] Socket reconnection take 2.
Date: Wed, 02 Dec 2009 20:13:52 +0000 [thread overview]
Message-ID: <4B16CA80.9010206@collabora.co.uk> (raw)
In-Reply-To: <4B16C62C.5090505@codemonkey.ws>
Reposting as requested. hopefully t-brid doesnt whitespace-mangle it.
Anthony Liguori wrote:
> > sleep() in qemu is very, very wrong. It will pause the guest's
> > execution and all sorts of badness can ensue.
Quite...
> > The right thing to do is set a timer and not generate data while
> > disconnected.
New patch attached, now with less crack...
> > I still am not confident this is really a great thing to do.
What other option is there than to drop the ability to feed entropy to
the guest when the hosts egd link drops?
btw. Does anyone know how to get t-bird to inline patches?
-Ian
>From e9d4be9cd0ef9e34c65939d4604874035c45bf34 Mon Sep 17 00:00:00 2001
From: Ian Molton <ian.molton@collabora.co.uk>
Date: Tue, 1 Dec 2009 11:18:41 +0000
Subject: [PATCH 2/4] socket: Add a reconnect option.
Add a reconnect option that allows sockets to reconnect (after a
specified delay) to the specified server. This makes the virtio-rng driver
useful in production environments where the EGD server may need to be
restarted.
Signed-off-by: Ian Molton <ian.molton@collabora.co.uk>
---
qemu-char.c | 177
++++++++++++++++++++++++++++++++++++++++++++-------------
qemu-char.h | 2 +
qemu-config.c | 3 +
vl.c | 4 +
4 files changed, 147 insertions(+), 39 deletions(-)
diff --git a/qemu-char.c b/qemu-char.c
index e202585..714c119 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -1870,8 +1870,12 @@ typedef struct {
int max_size;
int do_telnetopt;
int do_nodelay;
+ int reconnect;
int is_unix;
int msgfd;
+ QemuOpts *opts;
+ CharDriverState *chr;
+ int (*setup)(QemuOpts *opts);
} TCPCharDriver;
static void tcp_chr_accept(void *opaque);
@@ -2011,6 +2015,69 @@ static ssize_t tcp_chr_recv(CharDriverState *chr,
char *buf, size_t len)
}
#endif
+struct reconnect_list {
+ TCPCharDriver *s;
+ uint64_t when;
+ struct reconnect_list *next;
+};
+
+static struct reconnect_list *rc_list;
+
+static int qemu_chr_sched_reconnect(TCPCharDriver *s)
+{
+ struct reconnect_list *new = qemu_malloc(sizeof(*new));
+ struct timeval tv;
+
+ if(!new)
+ return 1;
+
+ gettimeofday(&tv, NULL);
+ new->s = s;
+ new->when = (s->reconnect + tv.tv_sec) * 1000000 + tv.tv_usec;
+ new->next = rc_list;
+ rc_list = new;
+
+ return 0;
+}
+
+static int qemu_chr_connect_socket(TCPCharDriver *s);
+
+void qemu_chr_reconnect(void)
+{
+ struct reconnect_list *this = rc_list, *prev = NULL;
+ struct timeval tv;
+ uint64_t now;
+
+ if(!this)
+ return;
+
+ gettimeofday(&tv, NULL);
+ now = tv.tv_sec * 1000000 + tv.tv_usec;
+
+ while (this) {
+ if (this->when <= now) {
+ if(qemu_chr_connect_socket(this->s)) {
+ if(prev)
+ prev->next = this->next;
+ else
+ rc_list = NULL;
+ qemu_chr_event(this->s->chr, CHR_EVENT_RECONNECTED);
+ free(this);
+ if(prev)
+ this = prev;
+ else
+ this = NULL;
+ }
+ else {
+ this->when += this->s->reconnect * 1000000;
+ }
+ }
+ prev = this;
+ if(this)
+ this = this->next;
+ }
+}
+
static void tcp_chr_read(void *opaque)
{
CharDriverState *chr = opaque;
@@ -2030,10 +2097,16 @@ static void tcp_chr_read(void *opaque)
if (s->listen_fd >= 0) {
qemu_set_fd_handler(s->listen_fd, tcp_chr_accept, NULL, chr);
}
- qemu_set_fd_handler(s->fd, NULL, NULL, NULL);
+ if (!s->reconnect)
+ qemu_set_fd_handler(s->fd, NULL, NULL, NULL);
closesocket(s->fd);
s->fd = -1;
- qemu_chr_event(chr, CHR_EVENT_CLOSED);
+ if (!s->reconnect) {
+ qemu_chr_event(chr, CHR_EVENT_CLOSED);
+ } else if (qemu_chr_sched_reconnect(s)) {
+ printf("Unable to queue socket for reconnection.\n");
+ qemu_chr_event(chr, CHR_EVENT_CLOSED);
+ }
} else if (size > 0) {
if (s->do_telnetopt)
tcp_chr_process_IAC_bytes(chr, s, buf, &size);
@@ -2137,7 +2210,6 @@ static CharDriverState
*qemu_chr_open_socket(QemuOpts *opts)
{
CharDriverState *chr = NULL;
TCPCharDriver *s = NULL;
- int fd = -1;
int is_listen;
int is_waitconnect;
int do_nodelay;
@@ -2145,34 +2217,40 @@ static CharDriverState
*qemu_chr_open_socket(QemuOpts *opts)
int is_telnet;
is_listen = qemu_opt_get_bool(opts, "server", 0);
+ is_unix = qemu_opt_get(opts, "path") != NULL;
+
is_waitconnect = qemu_opt_get_bool(opts, "wait", 1);
is_telnet = qemu_opt_get_bool(opts, "telnet", 0);
do_nodelay = !qemu_opt_get_bool(opts, "delay", 1);
- is_unix = qemu_opt_get(opts, "path") != NULL;
- if (!is_listen)
+
+ if (!is_listen) {
is_waitconnect = 0;
+ } else {
+ if (is_telnet)
+ s->do_telnetopt = 1;
+ }
+
- chr = qemu_mallocz(sizeof(CharDriverState));
s = qemu_mallocz(sizeof(TCPCharDriver));
+ chr = qemu_mallocz(sizeof(CharDriverState));
+ s->opts = opts;
+
+ if (!is_listen && !is_telnet)
+ s->reconnect = qemu_opt_get_number(opts, "reconnect", 0);
if (is_unix) {
if (is_listen) {
- fd = unix_listen_opts(opts);
+ s->setup = unix_listen_opts;
} else {
- fd = unix_connect_opts(opts);
+ s->setup = unix_connect_opts;
}
} else {
if (is_listen) {
- fd = inet_listen_opts(opts, 0);
+ s->setup = inet_listen_opts;
} else {
- fd = inet_connect_opts(opts);
+ s->setup = inet_connect_opts;
}
}
- if (fd < 0)
- goto fail;
-
- if (!is_waitconnect)
- socket_set_nonblock(fd);
s->connected = 0;
s->fd = -1;
@@ -2186,19 +2264,6 @@ static CharDriverState
*qemu_chr_open_socket(QemuOpts *opts)
chr->chr_close = tcp_chr_close;
chr->get_msgfd = tcp_get_msgfd;
- if (is_listen) {
- s->listen_fd = fd;
- qemu_set_fd_handler(s->listen_fd, tcp_chr_accept, NULL, chr);
- if (is_telnet)
- s->do_telnetopt = 1;
-
- } else {
- s->connected = 1;
- s->fd = fd;
- socket_set_nodelay(fd);
- tcp_chr_connect(chr);
- }
-
/* for "info chardev" monitor command */
chr->filename = qemu_malloc(256);
if (is_unix) {
@@ -2215,22 +2280,56 @@ static CharDriverState
*qemu_chr_open_socket(QemuOpts *opts)
qemu_opt_get_bool(opts, "server", 0) ? ",server" : "");
}
- if (is_listen && is_waitconnect) {
- printf("QEMU waiting for connection on: %s\n",
- chr->filename);
- tcp_chr_accept(chr);
- socket_set_nonblock(s->listen_fd);
- }
- return chr;
+ s->chr = chr;
+
+ if(qemu_chr_connect_socket(s))
+ return chr;
- fail:
- if (fd >= 0)
- closesocket(fd);
- qemu_free(s);
qemu_free(chr);
+ qemu_free(s);
+
return NULL;
}
+
+static int qemu_chr_connect_socket(TCPCharDriver *s)
+{
+ QemuOpts *opts = s->opts;
+ int is_listen;
+ int fd;
+ int is_waitconnect;
+ int do_nodelay;
+
+ is_waitconnect = qemu_opt_get_bool(opts, "wait", 1);
+ is_listen = qemu_opt_get_bool(opts, "server", 0);
+ do_nodelay = !qemu_opt_get_bool(opts, "delay", 1);
+
+
+ fd = s->setup(s->opts);
+ if (fd < 0)
+ return 0;
+
+ if (!is_waitconnect)
+ socket_set_nonblock(fd);
+
+ if (is_listen) {
+ s->listen_fd = fd;
+ qemu_set_fd_handler(s->listen_fd, tcp_chr_accept, NULL, s->chr);
+ if (is_waitconnect) {
+ printf("QEMU waiting for connection on: %s\n",
+ s->chr->filename);
+ tcp_chr_accept(s->chr);
+ socket_set_nonblock(s->listen_fd);
+ }
+ } else {
+ s->fd = fd;
+ socket_set_nodelay(fd);
+ tcp_chr_connect(s->chr);
+ }
+
+ return 1;
+}
+
static QemuOpts *qemu_chr_parse_compat(const char *label, const char
*filename)
{
char host[65], port[33], width[8], height[8];
diff --git a/qemu-char.h b/qemu-char.h
index 9957db1..dc954e2 100644
--- a/qemu-char.h
+++ b/qemu-char.h
@@ -14,6 +14,7 @@
#define CHR_EVENT_MUX_IN 3 /* mux-focus was set to this terminal */
#define CHR_EVENT_MUX_OUT 4 /* mux-focus will move on */
#define CHR_EVENT_CLOSED 5 /* connection closed */
+#define CHR_EVENT_RECONNECTED 6 /* reconnect event */
#define CHR_IOCTL_SERIAL_SET_PARAMS 1
@@ -73,6 +74,7 @@ CharDriverState *qemu_chr_open_opts(QemuOpts *opts,
void (*init)(struct CharDriverState
*s));
CharDriverState *qemu_chr_open(const char *label, const char *filename,
void (*init)(struct CharDriverState *s));
void qemu_chr_close(CharDriverState *chr);
+void qemu_chr_reconnect(void);
void qemu_chr_printf(CharDriverState *s, const char *fmt, ...);
int qemu_chr_write(CharDriverState *s, const uint8_t *buf, int len);
void qemu_chr_send_event(CharDriverState *s, int event);
diff --git a/qemu-config.c b/qemu-config.c
index 590fc05..ff8b06e 100644
--- a/qemu-config.c
+++ b/qemu-config.c
@@ -140,6 +140,9 @@ QemuOptsList qemu_chardev_opts = {
},{
.name = "signal",
.type = QEMU_OPT_BOOL,
+ },{
+ .name = "reconnect",
+ .type = QEMU_OPT_NUMBER,
},
{ /* end if list */ }
},
diff --git a/vl.c b/vl.c
index 44763af..5876c3e 100644
--- a/vl.c
+++ b/vl.c
@@ -3795,6 +3795,10 @@ void main_loop_wait(int timeout)
host_main_loop_wait(&timeout);
+ /* Reconnect any disconnected sockets, if necessary */
+
+ qemu_chr_reconnect();
+
/* poll any events */
/* XXX: separate device handlers from system ones */
nfds = -1;
-- 1.6.5
next prev parent reply other threads:[~2009-12-02 20:14 UTC|newest]
Thread overview: 40+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-12-02 16:46 [Qemu-devel] Staging update (0.12 pending freeze) Anthony Liguori
2009-12-02 19:22 ` [Qemu-devel] " Jan Kiszka
2009-12-02 19:32 ` Anthony Liguori
2009-12-03 14:23 ` Luiz Capitulino
2009-12-03 16:37 ` Luiz Capitulino
2009-12-03 16:44 ` Anthony Liguori
2009-12-02 19:44 ` [Qemu-devel] " Luiz Capitulino
2009-12-02 19:54 ` Anthony Liguori
2009-12-02 20:00 ` Luiz Capitulino
2009-12-02 19:46 ` Ian Molton
2009-12-02 19:48 ` Anthony Liguori
2009-12-02 19:52 ` Ian Molton
2009-12-02 19:55 ` Anthony Liguori
2009-12-02 20:13 ` Ian Molton [this message]
2009-12-03 10:33 ` [Qemu-devel] Re: [PATCH] Socket reconnection take 2 Michael S. Tsirkin
2009-12-03 12:34 ` [Qemu-devel] Staging update (0.12 pending freeze) Gerd Hoffmann
2009-12-03 13:08 ` Alexander Graf
2009-12-03 13:49 ` How to convert to -device & friends (was: [Qemu-devel] Staging update (0.12 pending freeze)) Markus Armbruster
2009-12-03 14:42 ` [Qemu-devel] Re: How to convert to -device & friends (was: " Michael S. Tsirkin
2009-12-03 23:21 ` [Qemu-devel] Staging update (0.12 pending freeze) Anthony Liguori
2009-12-03 23:53 ` Luiz Capitulino
2009-12-04 0:04 ` Anthony Liguori
2009-12-04 11:17 ` Gerd Hoffmann
2009-12-04 11:48 ` Luiz Capitulino
2009-12-04 12:43 ` Gerd Hoffmann
2009-12-04 14:12 ` Anthony Liguori
2009-12-03 13:52 ` [Qemu-devel] " Paolo Bonzini
2009-12-03 15:10 ` Anthony Liguori
2009-12-13 10:34 ` Paolo Bonzini
2009-12-03 15:27 ` [Qemu-devel] [FOR 0.12] [PATCH] virtio: Add memory statistics reporting to the balloon driver (V5) Adam Litke
2009-12-03 17:02 ` [Qemu-devel] [FOR 0.12] [PATCH] Updated: " Adam Litke
2009-12-03 16:57 ` [Qemu-devel] [FOR 0.12] debugcon patch for staging H. Peter Anvin
2009-12-03 19:26 ` [Qemu-devel] Staging update (0.12 pending freeze) Aurelien Jarno
2009-12-03 20:03 ` Blue Swirl
2009-12-05 20:05 ` Aurelien Jarno
2009-12-05 20:07 ` Blue Swirl
2009-12-06 11:59 ` Aurelien Jarno
2009-12-06 15:44 ` Blue Swirl
2009-12-07 22:24 ` Aurelien Jarno
2009-12-04 10:10 ` Kevin Wolf
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4B16CA80.9010206@collabora.co.uk \
--to=ian.molton@collabora.co.uk \
--cc=anthony@codemonkey.ws \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).