f375e62
From f249489e3f81a99bb60d1c008aabf9c8ad90b381 Mon Sep 17 00:00:00 2001
d4cdad5
From: Amit Shah <amit.shah@redhat.com>
d4cdad5
Date: Mon, 21 Mar 2011 22:02:47 +0100
5544c1b
Subject: [PATCH] char: Equip the unix/tcp backend to handle nonblocking
5544c1b
 writes#
d4cdad5
d4cdad5
Now that the infrastructure is in place to return -EAGAIN to callers,
d4cdad5
individual char drivers can set their update_fd_handlers() function to
d4cdad5
set or remove an fd's write handler.  This handler checks if the driver
d4cdad5
became writable.
d4cdad5
d4cdad5
A generic callback routine is used for unblocking writes and letting
d4cdad5
users of chardevs know that a driver became writable again.
d4cdad5
d4cdad5
Signed-off-by: Amit Shah <amit.shah@redhat.com>
bd56df9
Signed-off-by: Cole Robinson <crobinso@redhat.com>
d4cdad5
---
b6dd5ac
 qemu-char.c | 34 ++++++++++++++++++++++++++++++++++
329b588
 1 file changed, 34 insertions(+)
d4cdad5
d4cdad5
diff --git a/qemu-char.c b/qemu-char.c
5544c1b
index b46cc97..9f8608a 100644
d4cdad5
--- a/qemu-char.c
d4cdad5
+++ b/qemu-char.c
d4cdad5
@@ -106,6 +106,19 @@
d4cdad5
 static QTAILQ_HEAD(CharDriverStateHead, CharDriverState) chardevs =
d4cdad5
     QTAILQ_HEAD_INITIALIZER(chardevs);
329b588
 
d4cdad5
+/*
d4cdad5
+ * Generic routine that gets called when chardev becomes writable.
d4cdad5
+ * Lets chardev user know it's OK to send more data.
d4cdad5
+ */
d4cdad5
+static void char_write_unblocked(void *opaque)
d4cdad5
+{
d4cdad5
+    CharDriverState *chr = opaque;
d4cdad5
+
d4cdad5
+    chr->write_blocked = false;
d4cdad5
+    chr->chr_disable_write_fd_handler(chr);
d4cdad5
+    chr->chr_write_unblocked(chr->handler_opaque);
d4cdad5
+}
d4cdad5
+
d4cdad5
 void qemu_chr_be_event(CharDriverState *s, int event)
d4cdad5
 {
d4cdad5
     /* Keep track if the char device is open */
5544c1b
@@ -2503,6 +2516,25 @@ static void tcp_chr_close(CharDriverState *chr)
d4cdad5
     qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
d4cdad5
 }
329b588
 
d4cdad5
+static void tcp_enable_write_fd_handler(CharDriverState *chr)
d4cdad5
+{
d4cdad5
+    TCPCharDriver *s = chr->opaque;
d4cdad5
+
d4cdad5
+    /*
d4cdad5
+     * This function is called only after tcp_chr_connect() is called
d4cdad5
+     * (either in 'server' mode or client mode.  So we're sure of
d4cdad5
+     * s->fd being initialised.
d4cdad5
+     */
d4cdad5
+    enable_write_fd_handler(s->fd, char_write_unblocked);
d4cdad5
+}
d4cdad5
+
d4cdad5
+static void tcp_disable_write_fd_handler(CharDriverState *chr)
d4cdad5
+{
d4cdad5
+    TCPCharDriver *s = chr->opaque;
d4cdad5
+
d4cdad5
+    disable_write_fd_handler(s->fd);
d4cdad5
+}
d4cdad5
+
329b588
 static CharDriverState *qemu_chr_open_socket(QemuOpts *opts)
d4cdad5
 {
d4cdad5
     CharDriverState *chr = NULL;
5544c1b
@@ -2557,6 +2589,8 @@ static CharDriverState *qemu_chr_open_socket(QemuOpts *opts)
d4cdad5
     chr->chr_close = tcp_chr_close;
d4cdad5
     chr->get_msgfd = tcp_get_msgfd;
d4cdad5
     chr->chr_add_client = tcp_chr_add_client;
d4cdad5
+    chr->chr_enable_write_fd_handler = tcp_enable_write_fd_handler;
d4cdad5
+    chr->chr_disable_write_fd_handler = tcp_disable_write_fd_handler;
329b588
 
d4cdad5
     if (is_listen) {
d4cdad5
         s->listen_fd = fd;