aboutsummaryrefslogtreecommitdiffstats
path: root/tools/xenstore
diff options
context:
space:
mode:
Diffstat (limited to 'tools/xenstore')
-rw-r--r--tools/xenstore/xenstored_core.c191
-rw-r--r--tools/xenstore/xenstored_core.h2
2 files changed, 133 insertions, 60 deletions
diff --git a/tools/xenstore/xenstored_core.c b/tools/xenstore/xenstored_core.c
index bd44645370..a2cf2a66a3 100644
--- a/tools/xenstore/xenstored_core.c
+++ b/tools/xenstore/xenstored_core.c
@@ -19,7 +19,7 @@
#include <sys/types.h>
#include <sys/stat.h>
-#include <sys/select.h>
+#include <poll.h>
#ifndef NO_SOCKETS
#include <sys/socket.h>
#include <sys/un.h>
@@ -55,6 +55,12 @@
#include "hashtable.h"
extern xc_evtchn *xce_handle; /* in xenstored_domain.c */
+static int xce_pollfd_idx = -1;
+static struct pollfd *fds;
+static unsigned int current_array_size;
+static unsigned int nr_fds;
+
+#define ROUNDUP(_x, _w) (((unsigned long)(_x)+(1UL<<(_w))-1) & ~((1UL<<(_w))-1))
static bool verbose = false;
LIST_HEAD(connections);
@@ -62,6 +68,7 @@ static int tracefd = -1;
static bool recovery = true;
static bool remove_local = true;
static int reopen_log_pipe[2];
+static int reopen_log_pipe0_pollfd_idx = -1;
static char *tracefile = NULL;
static TDB_CONTEXT *tdb_ctx = NULL;
@@ -199,7 +206,7 @@ void trace_destroy(const void *data, const char *type)
/**
* Signal handler for SIGHUP, which requests that the trace log is reopened
* (in the main loop). A single byte is written to reopen_log_pipe, to awaken
- * the select() in the main loop.
+ * the poll() in the main loop.
*/
static void trigger_reopen_log(int signal __attribute__((unused)))
{
@@ -279,15 +286,12 @@ static int destroy_conn(void *_conn)
/* Flush outgoing if possible, but don't block. */
if (!conn->domain) {
- fd_set set;
- struct timeval none;
-
- FD_ZERO(&set);
- FD_SET(conn->fd, &set);
- none.tv_sec = none.tv_usec = 0;
+ struct pollfd pfd;
+ pfd.fd = conn->fd;
+ pfd.events = POLLOUT;
while (!list_empty(&conn->out_list)
- && select(conn->fd+1, NULL, &set, NULL, &none) == 1)
+ && poll(&pfd, 1, 0) == 1)
if (!write_messages(conn))
break;
close(conn->fd);
@@ -299,53 +303,77 @@ static int destroy_conn(void *_conn)
return 0;
}
-
-static void set_fd(int fd, fd_set *set, int *max)
+/* This function returns index inside the array if succeed, -1 if fail */
+static int set_fd(int fd, short events)
{
- if (fd < 0)
- return;
- FD_SET(fd, set);
- if (fd > *max)
- *max = fd;
-}
+ int ret;
+ if (current_array_size < nr_fds + 1) {
+ struct pollfd *new_fds = NULL;
+ unsigned long newsize;
+
+ /* Round up to 2^8 boundary, in practice this just
+ * make newsize larger than current_array_size.
+ */
+ newsize = ROUNDUP(nr_fds + 1, 8);
+
+ new_fds = realloc(fds, sizeof(struct pollfd)*newsize);
+ if (!new_fds)
+ goto fail;
+ fds = new_fds;
+
+ memset(&fds[0] + current_array_size, 0,
+ sizeof(struct pollfd ) * (newsize-current_array_size));
+ current_array_size = newsize;
+ }
+ fds[nr_fds].fd = fd;
+ fds[nr_fds].events = events;
+ ret = nr_fds;
+ nr_fds++;
-static int initialize_set(fd_set *inset, fd_set *outset, int sock, int ro_sock,
- struct timeval **ptimeout)
+ return ret;
+fail:
+ syslog(LOG_ERR, "realloc failed, ignoring fd %d\n", fd);
+ return -1;
+}
+
+static void initialize_fds(int sock, int *p_sock_pollfd_idx,
+ int ro_sock, int *p_ro_sock_pollfd_idx,
+ int *ptimeout)
{
- static struct timeval zero_timeout = { 0 };
struct connection *conn;
- int max = -1;
- *ptimeout = NULL;
+ if (fds)
+ memset(fds, 0, sizeof(struct pollfd) * current_array_size);
+ nr_fds = 0;
- FD_ZERO(inset);
- FD_ZERO(outset);
+ *ptimeout = -1;
if (sock != -1)
- set_fd(sock, inset, &max);
+ *p_sock_pollfd_idx = set_fd(sock, POLLIN|POLLPRI);
if (ro_sock != -1)
- set_fd(ro_sock, inset, &max);
+ *p_ro_sock_pollfd_idx = set_fd(ro_sock, POLLIN|POLLPRI);
if (reopen_log_pipe[0] != -1)
- set_fd(reopen_log_pipe[0], inset, &max);
+ reopen_log_pipe0_pollfd_idx =
+ set_fd(reopen_log_pipe[0], POLLIN|POLLPRI);
if (xce_handle != NULL)
- set_fd(xc_evtchn_fd(xce_handle), inset, &max);
+ xce_pollfd_idx = set_fd(xc_evtchn_fd(xce_handle),
+ POLLIN|POLLPRI);
list_for_each_entry(conn, &connections, list) {
if (conn->domain) {
if (domain_can_read(conn) ||
(domain_can_write(conn) &&
!list_empty(&conn->out_list)))
- *ptimeout = &zero_timeout;
+ *ptimeout = 0;
} else {
- set_fd(conn->fd, inset, &max);
+ short events = POLLIN|POLLPRI;
if (!list_empty(&conn->out_list))
- FD_SET(conn->fd, outset);
+ events |= POLLOUT;
+ conn->pollfd_idx = set_fd(conn->fd, events);
}
}
-
- return max;
}
/* Is child a subnode of parent, or equal? */
@@ -1330,6 +1358,7 @@ struct connection *new_connection(connwritefn_t *write, connreadfn_t *read)
return NULL;
new->fd = -1;
+ new->pollfd_idx = -1;
new->write = write;
new->read = read;
new->can_write = true;
@@ -1770,14 +1799,13 @@ int priv_domid = 0;
int main(int argc, char *argv[])
{
- int opt, *sock, *ro_sock, max;
- fd_set inset, outset;
+ int opt, *sock, *ro_sock;
+ int sock_pollfd_idx = -1, ro_sock_pollfd_idx = -1;
bool dofork = true;
bool outputpid = false;
bool no_domain_init = false;
const char *pidfile = NULL;
- int evtchn_fd = -1;
- struct timeval *timeout;
+ int timeout;
while ((opt = getopt_long(argc, argv, "DE:F:HNPS:t:T:RLVW:", options,
NULL)) != -1) {
@@ -1880,11 +1908,9 @@ int main(int argc, char *argv[])
signal(SIGHUP, trigger_reopen_log);
- if (xce_handle != NULL)
- evtchn_fd = xc_evtchn_fd(xce_handle);
-
/* Get ready to listen to the tools. */
- max = initialize_set(&inset, &outset, *sock, *ro_sock, &timeout);
+ initialize_fds(*sock, &sock_pollfd_idx, *ro_sock, &ro_sock_pollfd_idx,
+ &timeout);
/* Tell the kernel we're up and running. */
xenbus_notify_running();
@@ -1893,27 +1919,57 @@ int main(int argc, char *argv[])
for (;;) {
struct connection *conn, *next;
- if (select(max+1, &inset, &outset, NULL, timeout) < 0) {
+ if (poll(fds, nr_fds, timeout) < 0) {
if (errno == EINTR)
continue;
- barf_perror("Select failed");
+ barf_perror("Poll failed");
}
- if (reopen_log_pipe[0] != -1 && FD_ISSET(reopen_log_pipe[0], &inset)) {
- char c;
- if (read(reopen_log_pipe[0], &c, 1) != 1)
- barf_perror("read failed");
- reopen_log();
+ if (reopen_log_pipe0_pollfd_idx != -1) {
+ if (fds[reopen_log_pipe0_pollfd_idx].revents
+ & ~POLLIN) {
+ close(reopen_log_pipe[0]);
+ close(reopen_log_pipe[1]);
+ init_pipe(reopen_log_pipe);
+ } else if (fds[reopen_log_pipe0_pollfd_idx].revents
+ & POLLIN) {
+ char c;
+ if (read(reopen_log_pipe[0], &c, 1) != 1)
+ barf_perror("read failed");
+ reopen_log();
+ }
+ reopen_log_pipe0_pollfd_idx = -1;
}
- if (*sock != -1 && FD_ISSET(*sock, &inset))
- accept_connection(*sock, true);
+ if (sock_pollfd_idx != -1) {
+ if (fds[sock_pollfd_idx].revents & ~POLLIN) {
+ barf_perror("sock poll failed");
+ break;
+ } else if (fds[sock_pollfd_idx].revents & POLLIN) {
+ accept_connection(*sock, true);
+ sock_pollfd_idx = -1;
+ }
+ }
- if (*ro_sock != -1 && FD_ISSET(*ro_sock, &inset))
- accept_connection(*ro_sock, false);
+ if (ro_sock_pollfd_idx != -1) {
+ if (fds[ro_sock_pollfd_idx].revents & ~POLLIN) {
+ barf_perror("ro sock poll failed");
+ break;
+ } else if (fds[ro_sock_pollfd_idx].revents & POLLIN) {
+ accept_connection(*ro_sock, false);
+ ro_sock_pollfd_idx = -1;
+ }
+ }
- if (evtchn_fd != -1 && FD_ISSET(evtchn_fd, &inset))
- handle_event();
+ if (xce_pollfd_idx != -1) {
+ if (fds[xce_pollfd_idx].revents & ~POLLIN) {
+ barf_perror("xce_handle poll failed");
+ break;
+ } else if (fds[xce_pollfd_idx].revents & POLLIN) {
+ handle_event();
+ xce_pollfd_idx = -1;
+ }
+ }
next = list_entry(connections.next, typeof(*conn), list);
if (&next->list != &connections)
@@ -1939,21 +1995,36 @@ int main(int argc, char *argv[])
if (talloc_free(conn) == 0)
continue;
} else {
- if (FD_ISSET(conn->fd, &inset))
- handle_input(conn);
+ if (conn->pollfd_idx != -1) {
+ if (fds[conn->pollfd_idx].revents
+ & ~(POLLIN|POLLOUT))
+ talloc_free(conn);
+ else if (fds[conn->pollfd_idx].revents
+ & POLLIN)
+ handle_input(conn);
+ }
if (talloc_free(conn) == 0)
continue;
talloc_increase_ref_count(conn);
- if (FD_ISSET(conn->fd, &outset))
- handle_output(conn);
+
+ if (conn->pollfd_idx != -1) {
+ if (fds[conn->pollfd_idx].revents
+ & ~(POLLIN|POLLOUT))
+ talloc_free(conn);
+ else if (fds[conn->pollfd_idx].revents
+ & POLLOUT)
+ handle_output(conn);
+ }
if (talloc_free(conn) == 0)
continue;
+
+ conn->pollfd_idx = -1;
}
}
- max = initialize_set(&inset, &outset, *sock, *ro_sock,
- &timeout);
+ initialize_fds(*sock, &sock_pollfd_idx, *ro_sock,
+ &ro_sock_pollfd_idx, &timeout);
}
}
diff --git a/tools/xenstore/xenstored_core.h b/tools/xenstore/xenstored_core.h
index 492ca0d9a7..cfbcf6f3c3 100644
--- a/tools/xenstore/xenstored_core.h
+++ b/tools/xenstore/xenstored_core.h
@@ -60,6 +60,8 @@ struct connection
/* The file descriptor we came in on. */
int fd;
+ /* The index of pollfd in global pollfd array */
+ int pollfd_idx;
/* Who am I? 0 for socket connections. */
unsigned int id;