qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCHv3 RFC] qemu-kvm: stop devices on vmstop


From: Michael S. Tsirkin
Subject: [Qemu-devel] [PATCHv3 RFC] qemu-kvm: stop devices on vmstop
Date: Sun, 21 Nov 2010 21:16:42 +0200
User-agent: Mutt/1.5.21 (2010-09-15)

Stop running devices on vmstop, so that VM does not interact with
outside world at that time.

Whitelist system handlers which run even when VM is stopped.
These are specific handlers like monitor, gdbstub, migration.
I'm not really sure about ui: spice and vnc: do they need to run?

Untested.

Signed-off-by: Michael S. Tsirkin <address@hidden>
---

Change from previous versions:

reversed the approach, block all handlers except very specific ones.


 aio.c                  |   32 ++++++++-
 cmd.c                  |    8 +-
 gdbstub.c              |    2 +-
 migration-exec.c       |    4 +-
 migration-fd.c         |    4 +-
 migration-tcp.c        |    8 +-
 migration-unix.c       |    8 +-
 migration.c            |    8 +-
 qemu-aio.h             |    7 ++
 qemu-char.c            |   10 +++
 qemu-char.h            |    8 ++
 qemu-kvm.c             |    2 +-
 qemu-tool.c            |    9 +++
 ui/spice-core.c        |    2 +-
 ui/vnc-auth-sasl.c     |    2 +-
 ui/vnc-auth-vencrypt.c |    6 +-
 ui/vnc.c               |   14 ++--
 vl.c                   |  174 +++++++++++++++++++++++++++++++-----------------
 18 files changed, 210 insertions(+), 98 deletions(-)

diff --git a/aio.c b/aio.c
index 2f08655..0d50c87 100644
--- a/aio.c
+++ b/aio.c
@@ -52,14 +52,15 @@ static AioHandler *find_aio_handler(int fd)
     return NULL;
 }
 
-int qemu_aio_set_fd_handler(int fd,
+static int qemu_aio_assign_fd_handler(int fd,
                             IOHandler *io_read,
                             IOHandler *io_write,
                             AioFlushHandler *io_flush,
                             AioProcessQueue *io_process_queue,
-                            void *opaque)
+                            void *opaque, bool system)
 {
     AioHandler *node;
+    int r;
 
     node = find_aio_handler(fd);
 
@@ -93,11 +94,34 @@ int qemu_aio_set_fd_handler(int fd,
         node->opaque = opaque;
     }
 
-    qemu_set_fd_handler2(fd, NULL, io_read, io_write, opaque);
-
+    r = system ? qemu_set_fd_handler2(fd, NULL, io_read, io_write, opaque) :
+        qemu_set_system_fd_handler(fd, NULL, io_read, io_write, opaque);
+    assert(!r);
     return 0;
 }
 
+int qemu_aio_set_fd_handler(int fd,
+                            IOHandler *io_read,
+                            IOHandler *io_write,
+                            AioFlushHandler *io_flush,
+                            AioProcessQueue *io_process_queue,
+                            void *opaque)
+{
+    return qemu_aio_assign_fd_handler(fd, io_read, io_write, io_flush,
+                                      io_process_queue, opaque, false);
+}
+
+int qemu_aio_set_system_fd_handler(int fd,
+                            IOHandler *io_read,
+                            IOHandler *io_write,
+                            AioFlushHandler *io_flush,
+                            AioProcessQueue *io_process_queue,
+                            void *opaque)
+{
+    return qemu_aio_assign_fd_handler(fd, io_read, io_write, io_flush,
+                                      io_process_queue, opaque, true);
+}
+
 void qemu_aio_flush(void)
 {
     AioHandler *node;
diff --git a/cmd.c b/cmd.c
index db2c9c4..26dcfe4 100644
--- a/cmd.c
+++ b/cmd.c
@@ -154,7 +154,7 @@ static void prep_fetchline(void *opaque)
 {
     int *fetchable = opaque;
 
-    qemu_aio_set_fd_handler(STDIN_FILENO, NULL, NULL, NULL, NULL, NULL);
+    qemu_aio_set_system_fd_handler(STDIN_FILENO, NULL, NULL, NULL, NULL, NULL);
     *fetchable= 1;
 }
 
@@ -202,8 +202,8 @@ command_loop(void)
         if (!prompted) {
             printf("%s", get_prompt());
             fflush(stdout);
-            qemu_aio_set_fd_handler(STDIN_FILENO, prep_fetchline, NULL, NULL,
-                                    NULL, &fetchable);
+            qemu_aio_set_system_fd_handler(STDIN_FILENO, prep_fetchline,
+                                           NULL, NULL, NULL, &fetchable);
             prompted = 1;
         }
 
@@ -228,7 +228,7 @@ command_loop(void)
         prompted = 0;
         fetchable = 0;
        }
-    qemu_aio_set_fd_handler(STDIN_FILENO, NULL, NULL, NULL, NULL, NULL);
+    qemu_aio_set_system_fd_handler(STDIN_FILENO, NULL, NULL, NULL, NULL, NULL);
 }
 
 /* from libxcmd/input.c */
diff --git a/gdbstub.c b/gdbstub.c
index eb8465d..1dd53d9 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -2653,7 +2653,7 @@ int gdbserver_start(const char *device)
             sigaction(SIGINT, &act, NULL);
         }
 #endif
-        chr = qemu_chr_open("gdb", device, NULL);
+        chr = qemu_chr_open_system("gdb", device, NULL);
         if (!chr)
             return -1;
 
diff --git a/migration-exec.c b/migration-exec.c
index 14718dd..a8026bf 100644
--- a/migration-exec.c
+++ b/migration-exec.c
@@ -123,7 +123,7 @@ static void exec_accept_incoming_migration(void *opaque)
     QEMUFile *f = opaque;
 
     process_incoming_migration(f);
-    qemu_set_fd_handler2(qemu_stdio_fd(f), NULL, NULL, NULL, NULL);
+    qemu_set_system_fd_handler(qemu_stdio_fd(f), NULL, NULL, NULL, NULL);
     qemu_fclose(f);
 }
 
@@ -138,7 +138,7 @@ int exec_start_incoming_migration(const char *command)
         return -errno;
     }
 
-    qemu_set_fd_handler2(qemu_stdio_fd(f), NULL,
+    qemu_set_system_fd_handler(qemu_stdio_fd(f), NULL,
                         exec_accept_incoming_migration, NULL, f);
 
     return 0;
diff --git a/migration-fd.c b/migration-fd.c
index 6d14505..e7f8c1f 100644
--- a/migration-fd.c
+++ b/migration-fd.c
@@ -106,7 +106,7 @@ static void fd_accept_incoming_migration(void *opaque)
     QEMUFile *f = opaque;
 
     process_incoming_migration(f);
-    qemu_set_fd_handler2(qemu_stdio_fd(f), NULL, NULL, NULL, NULL);
+    qemu_set_system_fd_handler(qemu_stdio_fd(f), NULL, NULL, NULL, NULL);
     qemu_fclose(f);
 }
 
@@ -124,7 +124,7 @@ int fd_start_incoming_migration(const char *infd)
         return -errno;
     }
 
-    qemu_set_fd_handler2(fd, NULL, fd_accept_incoming_migration, NULL, f);
+    qemu_set_system_fd_handler(fd, NULL, fd_accept_incoming_migration, NULL, 
f);
 
     return 0;
 }
diff --git a/migration-tcp.c b/migration-tcp.c
index b55f419..7ea0f5b 100644
--- a/migration-tcp.c
+++ b/migration-tcp.c
@@ -66,7 +66,7 @@ static void tcp_wait_for_connect(void *opaque)
         return;
     }
 
-    qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);
+    qemu_set_system_fd_handler(s->fd, NULL, NULL, NULL, NULL);
 
     if (val == 0)
         migrate_fd_connect(s);
@@ -123,7 +123,7 @@ MigrationState *tcp_start_outgoing_migration(Monitor *mon,
             ret = -(s->get_error(s));
 
         if (ret == -EINPROGRESS || ret == -EWOULDBLOCK)
-            qemu_set_fd_handler2(s->fd, NULL, NULL, tcp_wait_for_connect, s);
+            qemu_set_system_fd_handler(s->fd, NULL, NULL, 
tcp_wait_for_connect, s);
     } while (ret == -EINTR);
 
     if (ret < 0 && ret != -EINPROGRESS && ret != -EWOULDBLOCK) {
@@ -165,7 +165,7 @@ static void tcp_accept_incoming_migration(void *opaque)
 out:
     close(c);
 out2:
-    qemu_set_fd_handler2(s, NULL, NULL, NULL, NULL);
+    qemu_set_system_fd_handler(s, NULL, NULL, NULL, NULL);
     close(s);
 }
 
@@ -193,7 +193,7 @@ int tcp_start_incoming_migration(const char *host_port)
     if (listen(s, 1) == -1)
         goto err;
 
-    qemu_set_fd_handler2(s, NULL, tcp_accept_incoming_migration, NULL,
+    qemu_set_system_fd_handler(s, NULL, tcp_accept_incoming_migration, NULL,
                          (void *)(unsigned long)s);
 
     return 0;
diff --git a/migration-unix.c b/migration-unix.c
index 57232c0..e32fe6b 100644
--- a/migration-unix.c
+++ b/migration-unix.c
@@ -65,7 +65,7 @@ static void unix_wait_for_connect(void *opaque)
         return;
     }
 
-    qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);
+    qemu_set_system_fd_handler(s->fd, NULL, NULL, NULL, NULL);
 
     if (val == 0)
         migrate_fd_connect(s);
@@ -118,7 +118,7 @@ MigrationState *unix_start_outgoing_migration(Monitor *mon,
            ret = -(s->get_error(s));
 
         if (ret == -EINPROGRESS || ret == -EWOULDBLOCK)
-           qemu_set_fd_handler2(s->fd, NULL, NULL, unix_wait_for_connect, s);
+           qemu_set_system_fd_handler(s->fd, NULL, NULL, 
unix_wait_for_connect, s);
     } while (ret == -EINTR);
 
     if (ret < 0 && ret != -EINPROGRESS && ret != -EWOULDBLOCK) {
@@ -171,7 +171,7 @@ static void unix_accept_incoming_migration(void *opaque)
     process_incoming_migration(f);
     qemu_fclose(f);
 out:
-    qemu_set_fd_handler2(s, NULL, NULL, NULL, NULL);
+    qemu_set_system_fd_handler(s, NULL, NULL, NULL, NULL);
     close(s);
     close(c);
 }
@@ -203,7 +203,7 @@ int unix_start_incoming_migration(const char *path)
         goto err;
     }
 
-    qemu_set_fd_handler2(sock, NULL, unix_accept_incoming_migration, NULL,
+    qemu_set_system_fd_handler(sock, NULL, unix_accept_incoming_migration, 
NULL,
                         (void *)(unsigned long)sock);
 
     return 0;
diff --git a/migration.c b/migration.c
index 9ee8b17..7597069 100644
--- a/migration.c
+++ b/migration.c
@@ -273,7 +273,7 @@ int migrate_fd_cleanup(FdMigrationState *s)
 {
     int ret = 0;
 
-    qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);
+    qemu_set_system_fd_handler(s->fd, NULL, NULL, NULL, NULL);
 
     if (s->file) {
         DPRINTF("closing file\n");
@@ -300,7 +300,7 @@ void migrate_fd_put_notify(void *opaque)
 {
     FdMigrationState *s = opaque;
 
-    qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);
+    qemu_set_system_fd_handler(s->fd, NULL, NULL, NULL, NULL);
     qemu_file_put_notify(s->file);
 }
 
@@ -317,7 +317,7 @@ ssize_t migrate_fd_put_buffer(void *opaque, const void 
*data, size_t size)
         ret = -(s->get_error(s));
 
     if (ret == -EAGAIN) {
-        qemu_set_fd_handler2(s->fd, NULL, NULL, migrate_fd_put_notify, s);
+        qemu_set_system_fd_handler(s->fd, NULL, NULL, migrate_fd_put_notify, 
s);
     } else if (ret < 0) {
         if (s->mon) {
             monitor_resume(s->mon);
@@ -445,6 +445,6 @@ int migrate_fd_close(void *opaque)
 {
     FdMigrationState *s = opaque;
 
-    qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);
+    qemu_set_system_fd_handler(s->fd, NULL, NULL, NULL, NULL);
     return s->close(s);
 }
diff --git a/qemu-aio.h b/qemu-aio.h
index 3bdd749..4223d34 100644
--- a/qemu-aio.h
+++ b/qemu-aio.h
@@ -56,4 +56,11 @@ int qemu_aio_set_fd_handler(int fd,
                             AioProcessQueue *io_process_queue,
                             void *opaque);
 
+/* Same but for system handlers, which run when VM is stopped. */
+int qemu_aio_set_system_fd_handler(int fd,
+                            IOHandler *io_read,
+                            IOHandler *io_write,
+                            AioFlushHandler *io_flush,
+                            AioProcessQueue *io_process_queue,
+                            void *opaque);
 #endif
diff --git a/qemu-char.c b/qemu-char.c
index 88997f9..6a26787 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -2500,6 +2500,16 @@ CharDriverState *qemu_chr_open(const char *label, const 
char *filename, void (*i
     return chr;
 }
 
+CharDriverState *qemu_chr_system_open(const char *label,
+                                      const char *filename, void 
(*init)(struct CharDriverState *s))
+{
+    CharDriverState *chr = qemu_chr_open(label, filename, init);
+    if (chr) {
+        chr->system = 1;
+    }
+    return chr;
+}
+
 void qemu_chr_close(CharDriverState *chr)
 {
     QTAILQ_REMOVE(&chardevs, chr, next);
diff --git a/qemu-char.h b/qemu-char.h
index 18ad12b..2f35fc9 100644
--- a/qemu-char.h
+++ b/qemu-char.h
@@ -68,6 +68,7 @@ struct CharDriverState {
     char *label;
     char *filename;
     int opened;
+    int system;
     QTAILQ_ENTRY(CharDriverState) next;
 };
 
@@ -75,6 +76,8 @@ QemuOpts *qemu_chr_parse_compat(const char *label, const char 
*filename);
 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));
+CharDriverState *qemu_chr_system_open(const char *label, const char *filename,
+                                     void (*init)(struct CharDriverState *s));
 void qemu_chr_close(CharDriverState *chr);
 void qemu_chr_printf(CharDriverState *s, const char *fmt, ...)
     GCC_FMT_ATTR(2, 3);
@@ -111,4 +114,9 @@ int qemu_set_fd_handler(int fd,
                         IOHandler *fd_read,
                         IOHandler *fd_write,
                         void *opaque);
+int qemu_set_system_fd_handler(int fd,
+                         IOCanReadHandler *fd_read_poll,
+                         IOHandler *fd_read,
+                         IOHandler *fd_write,
+                         void *opaque);
 #endif
diff --git a/qemu-kvm.c b/qemu-kvm.c
index 471306b..c99b597 100644
--- a/qemu-kvm.c
+++ b/qemu-kvm.c
@@ -1577,7 +1577,7 @@ int kvm_main_loop(void)
 
     fcntl(sigfd, F_SETFL, O_NONBLOCK);
 
-    qemu_set_fd_handler2(sigfd, NULL, sigfd_handler, NULL,
+    qemu_set_system_fd_handler(sigfd, NULL, sigfd_handler, NULL,
                          (void *)(unsigned long) sigfd);
 
     pthread_cond_broadcast(&qemu_system_cond);
diff --git a/qemu-tool.c b/qemu-tool.c
index 392e1c9..0255ff3 100644
--- a/qemu-tool.c
+++ b/qemu-tool.c
@@ -111,3 +111,12 @@ int qemu_set_fd_handler2(int fd,
 {
     return 0;
 }
+
+int qemu_set_system_fd_handler(int fd,
+                               IOCanReadHandler *fd_read_poll,
+                               IOHandler *fd_read,
+                               IOHandler *fd_write,
+                               void *opaque)
+{
+    return 0;
+}
diff --git a/ui/spice-core.c b/ui/spice-core.c
index 6c404b3..fdcb303 100644
--- a/ui/spice-core.c
+++ b/ui/spice-core.c
@@ -97,7 +97,7 @@ static void watch_update_mask(SpiceWatch *watch, int 
event_mask)
     if (watch->event_mask & SPICE_WATCH_EVENT_WRITE) {
         on_read = watch_write;
     }
-    qemu_set_fd_handler(watch->fd, on_read, on_write, watch);
+    qemu_set_system_fd_handler(watch->fd, NULL, on_read, on_write, watch);
 }
 
 static SpiceWatch *watch_add(int fd, int event_mask, SpiceWatchFunc func, void 
*opaque)
diff --git a/ui/vnc-auth-sasl.c b/ui/vnc-auth-sasl.c
index a51ddc8..58f199b 100644
--- a/ui/vnc-auth-sasl.c
+++ b/ui/vnc-auth-sasl.c
@@ -84,7 +84,7 @@ long vnc_client_write_sasl(VncState *vs)
      * SASL encoded output
      */
     if (vs->output.offset == 0) {
-        qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, NULL, vs);
+        qemu_set_systemk_fd_handler(vs->csock, NULL, vnc_client_read, NULL, 
vs);
     }
 
     return ret;
diff --git a/ui/vnc-auth-vencrypt.c b/ui/vnc-auth-vencrypt.c
index 07c1691..489fc11 100644
--- a/ui/vnc-auth-vencrypt.c
+++ b/ui/vnc-auth-vencrypt.c
@@ -71,9 +71,9 @@ static int vnc_start_vencrypt_handshake(struct VncState *vs) {
        if (!gnutls_error_is_fatal(ret)) {
            VNC_DEBUG("Handshake interrupted (blocking)\n");
            if (!gnutls_record_get_direction(vs->tls.session))
-               qemu_set_fd_handler(vs->csock, vnc_tls_handshake_io, NULL, vs);
+               qemu_set_system_fd_handler(vs->csock, NULL, 
vnc_tls_handshake_io, NULL, vs);
            else
-               qemu_set_fd_handler(vs->csock, NULL, vnc_tls_handshake_io, vs);
+               qemu_set_system_fd_handler(vs->csock, NULL, NULL, 
vnc_tls_handshake_io, vs);
            return 0;
        }
        VNC_DEBUG("Handshake failed %s\n", gnutls_strerror(ret));
@@ -93,7 +93,7 @@ static int vnc_start_vencrypt_handshake(struct VncState *vs) {
 
     VNC_DEBUG("Handshake done, switching to TLS data mode\n");
     vs->tls.wiremode = VNC_WIREMODE_TLS;
-    qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, vnc_client_write, 
vs);
+    qemu_set_system_fd_handler(vs->csock, NULL, vnc_client_read, 
vnc_client_write, vs);
 
     start_auth_vencrypt_subauth(vs);
 
diff --git a/ui/vnc.c b/ui/vnc.c
index 864342e..b7bdddf 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -1005,7 +1005,7 @@ static void vnc_disconnect_start(VncState *vs)
 {
     if (vs->csock == -1)
         return;
-    qemu_set_fd_handler2(vs->csock, NULL, NULL, NULL, NULL);
+    qemu_set_system_fd_handler(vs->csock, NULL, NULL, NULL, NULL);
     closesocket(vs->csock);
     vs->csock = -1;
 }
@@ -1155,7 +1155,7 @@ static long vnc_client_write_plain(VncState *vs)
     vs->output.offset -= ret;
 
     if (vs->output.offset == 0) {
-        qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, NULL, vs);
+        qemu_set_system_fd_handler(vs->csock, NULL, vnc_client_read, NULL, vs);
     }
 
     return ret;
@@ -1189,7 +1189,7 @@ void vnc_client_write(void *opaque)
     if (vs->output.offset) {
         vnc_client_write_locked(opaque);
     } else if (vs->csock != -1) {
-        qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, NULL, vs);
+        qemu_set_system_fd_handler(vs->csock, NULL, vnc_client_read, NULL, vs);
     }
     vnc_unlock_output(vs);
 }
@@ -1305,7 +1305,7 @@ void vnc_write(VncState *vs, const void *data, size_t len)
     buffer_reserve(&vs->output, len);
 
     if (vs->csock != -1 && buffer_empty(&vs->output)) {
-        qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, 
vnc_client_write, vs);
+        qemu_set_system_fd_handler(vs->csock, NULL, vnc_client_read, 
vnc_client_write, vs);
     }
 
     buffer_append(&vs->output, data, len);
@@ -2369,7 +2369,7 @@ static void vnc_connect(VncDisplay *vd, int csock)
     VNC_DEBUG("New client on socket %d\n", csock);
     dcl->idle = 0;
     socket_set_nonblock(vs->csock);
-    qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, NULL, vs);
+    qemu_set_system_fd_handler(vs->csock, NULL, vnc_client_read, NULL, vs);
 
     vnc_client_cache_addr(vs);
     vnc_qmp_event(vs, QEVENT_VNC_CONNECTED);
@@ -2471,7 +2471,7 @@ void vnc_display_close(DisplayState *ds)
         vs->display = NULL;
     }
     if (vs->lsock != -1) {
-        qemu_set_fd_handler2(vs->lsock, NULL, NULL, NULL, NULL);
+        qemu_set_system_fd_handler(vs->lsock, NULL, NULL, NULL, NULL);
         close(vs->lsock);
         vs->lsock = -1;
     }
@@ -2736,5 +2736,5 @@ int vnc_display_open(DisplayState *ds, const char 
*display)
             vs->display = dpy;
         }
     }
-    return qemu_set_fd_handler2(vs->lsock, NULL, vnc_listen_read, NULL, vs);
+    return qemu_set_system_fd_handler(vs->lsock, NULL, vnc_listen_read, NULL, 
vs);
 }
diff --git a/vl.c b/vl.c
index 37ed560..1d50e00 100644
--- a/vl.c
+++ b/vl.c
@@ -929,34 +929,36 @@ typedef struct IOHandlerRecord {
     QLIST_ENTRY(IOHandlerRecord) next;
 } IOHandlerRecord;
 
-static QLIST_HEAD(, IOHandlerRecord) io_handlers =
-    QLIST_HEAD_INITIALIZER(io_handlers);
+typedef QLIST_HEAD(, IOHandlerRecord) IOHandlerRecordList;
+static IOHandlerRecordList device_io_handlers =
+    QLIST_HEAD_INITIALIZER(device_io_handlers);
 
+static IOHandlerRecordList system_io_handlers =
+    QLIST_HEAD_INITIALIZER(system_io_handlers);
 
-/* XXX: fd_read_poll should be suppressed, but an API change is
-   necessary in the character devices to suppress fd_can_read(). */
-int qemu_set_fd_handler2(int fd,
-                         IOCanReadHandler *fd_read_poll,
-                         IOHandler *fd_read,
-                         IOHandler *fd_write,
-                         void *opaque)
+static int qemu_assign_fd_handler(int fd,
+                                  IOCanReadHandler *fd_read_poll,
+                                  IOHandler *fd_read,
+                                  IOHandler *fd_write,
+                                  void *opaque,
+                                  IOHandlerRecordList *list)
 {
     IOHandlerRecord *ioh;
 
     if (!fd_read && !fd_write) {
-        QLIST_FOREACH(ioh, &io_handlers, next) {
+        QLIST_FOREACH(ioh, list, next) {
             if (ioh->fd == fd) {
                 ioh->deleted = 1;
                 break;
             }
         }
     } else {
-        QLIST_FOREACH(ioh, &io_handlers, next) {
+        QLIST_FOREACH(ioh, list, next) {
             if (ioh->fd == fd)
                 goto found;
         }
         ioh = qemu_mallocz(sizeof(IOHandlerRecord));
-        QLIST_INSERT_HEAD(&io_handlers, ioh, next);
+        QLIST_INSERT_HEAD(list, ioh, next);
     found:
         ioh->fd = fd;
         ioh->fd_read_poll = fd_read_poll;
@@ -969,6 +971,19 @@ int qemu_set_fd_handler2(int fd,
     return 0;
 }
 
+
+/* XXX: fd_read_poll should be suppressed, but an API change is
+   necessary in the character devices to suppress fd_can_read(). */
+int qemu_set_fd_handler2(int fd,
+                         IOCanReadHandler *fd_read_poll,
+                         IOHandler *fd_read,
+                         IOHandler *fd_write,
+                         void *opaque)
+{
+    return qemu_assign_fd_handler(fd, fd_read_poll, fd_read, fd_write, opaque,
+                                  &device_io_handlers);
+}
+
 int qemu_set_fd_handler(int fd,
                         IOHandler *fd_read,
                         IOHandler *fd_write,
@@ -977,6 +992,18 @@ int qemu_set_fd_handler(int fd,
     return qemu_set_fd_handler2(fd, NULL, fd_read, fd_write, opaque);
 }
 
+int qemu_set_system_fd_handler(int fd,
+                         IOCanReadHandler *fd_read_poll,
+                         IOHandler *fd_read,
+                         IOHandler *fd_write,
+                         void *opaque)
+{
+    qemu_assign_fd_handler(fd, fd_read_poll, fd_read, fd_write, opaque,
+                                  &device_io_handlers);
+    return qemu_assign_fd_handler(fd, fd_read_poll, fd_read, fd_write, opaque,
+                                  &system_io_handlers);
+}
+
 /***********************************************************/
 /* machine registration */
 
@@ -1213,13 +1240,57 @@ void qemu_system_powerdown_request(void)
     qemu_notify_event();
 }
 
-void main_loop_wait(int nonblocking)
+static inline int get_ioh_fds(IOHandlerRecordList *list,
+                              int nfds, fd_set *rfds, fd_set *wfds)
 {
     IOHandlerRecord *ioh;
+    QLIST_FOREACH(ioh, list, next) {
+        if (ioh->deleted)
+            continue;
+        if (ioh->fd_read &&
+            (!ioh->fd_read_poll ||
+             ioh->fd_read_poll(ioh->opaque) != 0)) {
+            FD_SET(ioh->fd, rfds);
+            if (ioh->fd > nfds)
+                nfds = ioh->fd;
+        }
+        if (ioh->fd_write) {
+            FD_SET(ioh->fd, wfds);
+            if (ioh->fd > nfds)
+                nfds = ioh->fd;
+        }
+    }
+    return nfds;
+}
+
+static inline void call_ioh_fds(IOHandlerRecordList *list,
+                                  fd_set *rfds, fd_set *wfds)
+{
+    IOHandlerRecord *ioh, *pioh;
+
+    QLIST_FOREACH_SAFE(ioh, list, next, pioh) {
+        if (ioh->deleted) {
+            QLIST_REMOVE(ioh, next);
+            qemu_free(ioh);
+            continue;
+        }
+        if (ioh->fd_read && FD_ISSET(ioh->fd, rfds)) {
+            ioh->fd_read(ioh->opaque);
+            if (!(ioh->fd_read_poll && ioh->fd_read_poll(ioh->opaque)))
+                FD_CLR(ioh->fd, rfds);
+        }
+        if (ioh->fd_write && FD_ISSET(ioh->fd, wfds)) {
+            ioh->fd_write(ioh->opaque);
+        }
+    }
+}
+void main_loop_wait(int nonblocking)
+{
     fd_set rfds, wfds, xfds;
     int ret, nfds;
     struct timeval tv;
     int timeout;
+    IOHandlerRecordList *handlers;
 
     if (nonblocking)
         timeout = 0;
@@ -1231,64 +1302,47 @@ void main_loop_wait(int nonblocking)
     os_host_main_loop_wait(&timeout);
 
     /* poll any events */
-    /* XXX: separate device handlers from system ones */
     nfds = -1;
     FD_ZERO(&rfds);
     FD_ZERO(&wfds);
     FD_ZERO(&xfds);
-    QLIST_FOREACH(ioh, &io_handlers, next) {
-        if (ioh->deleted)
-            continue;
-        if (ioh->fd_read &&
-            (!ioh->fd_read_poll ||
-             ioh->fd_read_poll(ioh->opaque) != 0)) {
-            FD_SET(ioh->fd, &rfds);
-            if (ioh->fd > nfds)
-                nfds = ioh->fd;
-        }
-        if (ioh->fd_write) {
-            FD_SET(ioh->fd, &wfds);
-            if (ioh->fd > nfds)
-                nfds = ioh->fd;
-        }
-    }
 
-    tv.tv_sec = timeout / 1000;
-    tv.tv_usec = (timeout % 1000) * 1000;
+    if (vm_running) {
 
-    slirp_select_fill(&nfds, &rfds, &wfds, &xfds);
+        nfds = get_ioh_fds(&device_io_handlers, nfds, &rfds, &wfds);
 
-    qemu_mutex_unlock_iothread();
-    ret = select(nfds + 1, &rfds, &wfds, &xfds, &tv);
-    qemu_mutex_lock_iothread();
-    if (ret > 0) {
-        IOHandlerRecord *pioh;
+        tv.tv_sec = timeout / 1000;
+        tv.tv_usec = (timeout % 1000) * 1000;
 
-        QLIST_FOREACH_SAFE(ioh, &io_handlers, next, pioh) {
-            if (ioh->deleted) {
-                QLIST_REMOVE(ioh, next);
-                qemu_free(ioh);
-                continue;
-            }
-            if (ioh->fd_read && FD_ISSET(ioh->fd, &rfds)) {
-                ioh->fd_read(ioh->opaque);
-                if (!(ioh->fd_read_poll && ioh->fd_read_poll(ioh->opaque)))
-                    FD_CLR(ioh->fd, &rfds);
-            }
-            if (ioh->fd_write && FD_ISSET(ioh->fd, &wfds)) {
-                ioh->fd_write(ioh->opaque);
-            }
+        slirp_select_fill(&nfds, &rfds, &wfds, &xfds);
+
+        qemu_mutex_unlock_iothread();
+        ret = select(nfds + 1, &rfds, &wfds, &xfds, &tv);
+        qemu_mutex_lock_iothread();
+        if (ret > 0) {
+            call_ioh_fds(&device_io_handlers, &rfds, &wfds);
         }
-    }
 
-    slirp_select_poll(&rfds, &wfds, &xfds, (ret < 0));
+        slirp_select_poll(&rfds, &wfds, &xfds, (ret < 0));
 
-    qemu_run_all_timers();
+        qemu_run_all_timers();
 
-    /* Check bottom-halves last in case any of the earlier events triggered
-       them.  */
-    qemu_bh_poll();
+        /* Check bottom-halves last in case any of the earlier events triggered
+           them.  */
+        qemu_bh_poll();
+    } else {
+        nfds = get_ioh_fds(&system_io_handlers, nfds, &rfds, &wfds);
+
+        tv.tv_sec = timeout / 1000;
+        tv.tv_usec = (timeout % 1000) * 1000;
 
+        qemu_mutex_unlock_iothread();
+        ret = select(nfds + 1, &rfds, &wfds, &xfds, &tv);
+        qemu_mutex_lock_iothread();
+        if (ret > 0) {
+            call_ioh_fds(&system_io_handlers, &rfds, &wfds);
+        }
+    }
 }
 
 static int vm_can_run(void)
-- 
1.7.3.2.91.g446ac



reply via email to

[Prev in Thread] Current Thread [Next in Thread]