diff -rup xen-3.1.0-src/tools/console/daemon/io.c xen-3.1.0-src.new/tools/console/daemon/io.c
--- xen-3.1.0-src/tools/console/daemon/io.c 2007-05-18 10:45:21.000000000 -0400
+++ xen-3.1.0-src.new/tools/console/daemon/io.c 2007-06-12 10:27:43.000000000 -0400
@@ -44,6 +44,14 @@
/* Each 10 bits takes ~ 3 digits, plus one, plus one for nul terminator. */
#define MAX_STRLEN(x) ((sizeof(x) * CHAR_BIT + CHAR_BIT-1) / 10 * 3 + 2)
+extern int log_reload;
+extern int log_guest;
+extern int log_hv;
+extern char *log_dir;
+
+static int log_hv_fd = -1;
+static int xc_handle = -1;
+
struct buffer
{
char *data;
@@ -57,6 +65,7 @@ struct domain
{
int domid;
int tty_fd;
+ int log_fd;
bool is_dead;
struct buffer buffer;
struct domain *next;
@@ -103,6 +112,19 @@ static void buffer_append(struct domain
intf->out_cons = cons;
xc_evtchn_notify(dom->xce_handle, dom->local_port);
+ /* Get the data to the logfile as early as possible because if
+ * no one is listening on the console pty then it will fill up
+ * and handle_tty_write will stop being called.
+ */
+ if (dom->log_fd != -1) {
+ int len = write(dom->log_fd,
+ buffer->data + buffer->size - size,
+ size);
+ if (len < 0)
+ dolog(LOG_ERR, "Write to log failed on domain %d: %d (%s)\n",
+ dom->domid, errno, strerror(errno));
+ }
+
if (buffer->max_capacity &&
buffer->size > buffer->max_capacity) {
/* Discard the middle of the data. */
@@ -144,6 +166,54 @@ static bool domain_is_valid(int domid)
return ret;
}
+static int create_hv_log(void)
+{
+ char logfile[PATH_MAX];
+ int fd;
+ snprintf(logfile, PATH_MAX-1, "%s/hypervisor.log", log_dir);
+ logfile[PATH_MAX-1] = '\0';
+
+ fd = open(logfile, O_WRONLY|O_CREAT|O_APPEND, 0644);
+ if (fd == -1)
+ dolog(LOG_ERR, "Failed to open log %s: %d (%s)",
+ logfile, errno, strerror(errno));
+ return fd;
+}
+
+static int create_domain_log(struct domain *dom)
+{
+ char logfile[PATH_MAX];
+ char *namepath, *data, *s;
+ int fd, len;
+
+ namepath = xs_get_domain_path(xs, dom->domid);
+ s = realloc(namepath, strlen(namepath) + 6);
+ if (s == NULL) {
+ free(namepath);
+ return -1;
+ }
+ namepath = s;
+ strcat(namepath, "/name");
+ data = xs_read(xs, XBT_NULL, namepath, &len);
+ if (!data)
+ return -1;
+ if (!len) {
+ free(data);
+ return -1;
+ }
+
+ snprintf(logfile, PATH_MAX-1, "%s/guest-%s.log", log_dir, data);
+ free(data);
+ logfile[PATH_MAX-1] = '\0';
+
+ fd = open(logfile, O_WRONLY|O_CREAT|O_APPEND, 0644);
+ if (fd == -1)
+ dolog(LOG_ERR, "Failed to open log %s: %d (%s)",
+ logfile, errno, strerror(errno));
+ return fd;
+}
+
+
static int domain_create_tty(struct domain *dom)
{
char *path;
@@ -325,6 +395,9 @@ static int domain_create_ring(struct dom
}
}
+ if (log_guest)
+ dom->log_fd = create_domain_log(dom);
+
out:
return err;
}
@@ -352,6 +425,7 @@ static bool watch_domain(struct domain *
return success;
}
+
static struct domain *create_domain(int domid)
{
struct domain *dom;
@@ -383,6 +457,8 @@ static struct domain *create_domain(int
strcat(dom->conspath, "/console");
dom->tty_fd = -1;
+ dom->log_fd = -1;
+
dom->is_dead = false;
dom->buffer.data = 0;
dom->buffer.consumed = 0;
@@ -444,6 +520,10 @@ static void cleanup_domain(struct domain
close(d->tty_fd);
d->tty_fd = -1;
}
+ if (d->log_fd != -1) {
+ close(d->log_fd);
+ d->log_fd = -1;
+ }
free(d->buffer.data);
d->buffer.data = NULL;
@@ -605,13 +685,54 @@ static void handle_xs(void)
free(vec);
}
+static void handle_hv_logs(void)
+{
+ char buffer[1024*16];
+ char *bufptr = buffer;
+ unsigned int size = sizeof(buffer);
+ if (xc_readconsolering(xc_handle, &bufptr, &size, 1) == 0) {
+ int len = write(log_hv_fd, buffer, size);
+ if (len < 0)
+ dolog(LOG_ERR, "Failed to write hypervisor log: %d (%s)",
+ errno, strerror(errno));
+ }
+}
+
+static void handle_log_reload(void)
+{
+ if (log_guest) {
+ struct domain *d;
+ for (d = dom_head; d; d = d->next) {
+ if (d->log_fd != -1)
+ close(d->log_fd);
+ d->log_fd = create_domain_log(d);
+ }
+ }
+
+ if (log_hv) {
+ if (log_hv_fd != -1)
+ close(log_hv_fd);
+ log_hv_fd = create_hv_log();
+ }
+}
+
void handle_io(void)
{
fd_set readfds, writefds;
int ret;
- do {
+ if (log_hv) {
+ xc_handle = xc_interface_open();
+ if (xc_handle == -1)
+ dolog(LOG_ERR, "Failed to open xc handle: %d (%s)",
+ errno, strerror(errno));
+ else
+ log_hv_fd = create_hv_log();
+ }
+
+ for (;;) {
struct domain *d, *n;
+ struct timeval timeout = { 1, 0 }; /* Read HV logs every 1 second */
int max_fd = -1;
FD_ZERO(&readfds);
@@ -637,7 +758,34 @@ void handle_io(void)
}
}
- ret = select(max_fd + 1, &readfds, &writefds, 0, NULL);
+ /* XXX I wish we didn't have to busy wait for hypervisor logs
+ * but there's no obvious way to get event channel notifications
+ * for new HV log data as we can with guest */
+ ret = select(max_fd + 1, &readfds, &writefds, 0, log_hv_fd != -1 ? &timeout : NULL);
+
+ if (log_reload) {
+ handle_log_reload();
+ log_reload = 0;
+ }
+
+ /* Abort if select failed, except for EINTR cases
+ which indicate a possible log reload */
+ if (ret == -1) {
+ if (errno == EINTR)
+ continue;
+ dolog(LOG_ERR, "Failure in select: %d (%s)",
+ errno, strerror(errno));
+ break;
+ }
+
+ /* Always process HV logs even if not a timeout */
+ if (log_hv_fd != -1)
+ handle_hv_logs();
+
+ /* Must not check return FDSET if it was a timeout */
+ if (ret == 0) {
+ continue;
+ }
if (FD_ISSET(xs_fileno(xs), &readfds))
handle_xs();
@@ -657,7 +805,16 @@ void handle_io(void)
if (d->is_dead)
cleanup_domain(d);
}
- } while (ret > -1);
+ }
+
+ if (log_hv_fd != -1) {
+ close(log_hv_fd);
+ log_hv_fd = -1;
+ }
+ if (xc_handle != -1) {
+ xc_interface_close(xc_handle);
+ xc_handle = -1;
+ }
}
/*
diff -rup xen-3.1.0-src/tools/console/daemon/main.c xen-3.1.0-src.new/tools/console/daemon/main.c
--- xen-3.1.0-src/tools/console/daemon/main.c 2007-05-18 10:45:21.000000000 -0400
+++ xen-3.1.0-src.new/tools/console/daemon/main.c 2007-06-12 09:32:51.000000000 -0400
@@ -23,6 +23,8 @@
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
+#include <string.h>
+#include <signal.h>
#include <sys/types.h>
#include "xenctrl.h"
@@ -30,9 +32,19 @@
#include "utils.h"
#include "io.h"
+int log_reload = 0;
+int log_guest = 0;
+int log_hv = 0;
+char *log_dir = NULL;
+
+static void handle_hup(int sig)
+{
+ log_reload = 1;
+}
+
static void usage(char *name)
{
- printf("Usage: %s [-h] [-V] [-v] [-i]\n", name);
+ printf("Usage: %s [-h] [-V] [-v] [-i] [--log=none|guest|hv|all] [--log-dir=DIR] [--pid-file=PATH]\n", name);
}
static void version(char *name)
@@ -48,6 +60,9 @@ int main(int argc, char **argv)
{ "version", 0, 0, 'V' },
{ "verbose", 0, 0, 'v' },
{ "interactive", 0, 0, 'i' },
+ { "log", 1, 0, 'l' },
+ { "log-dir", 1, 0, 'r' },
+ { "pid-file", 1, 0, 'p' },
{ 0 },
};
bool is_interactive = false;
@@ -55,6 +70,7 @@ int main(int argc, char **argv)
int syslog_option = LOG_CONS;
int syslog_mask = LOG_WARNING;
int opt_ind = 0;
+ char *pidfile = NULL;
while ((ch = getopt_long(argc, argv, sopts, lopts, &opt_ind)) != -1) {
switch (ch) {
@@ -71,6 +87,22 @@ int main(int argc, char **argv)
case 'i':
is_interactive = true;
break;
+ case 'l':
+ if (!strcmp(optarg, "all")) {
+ log_hv = 1;
+ log_guest = 1;
+ } else if (!strcmp(optarg, "hv")) {
+ log_hv = 1;
+ } else if (!strcmp(optarg, "guest")) {
+ log_guest = 1;
+ }
+ break;
+ case 'r':
+ log_dir = strdup(optarg);
+ break;
+ case 'p':
+ pidfile = strdup(optarg);
+ break;
case '?':
fprintf(stderr,
"Try `%s --help' for more information\n",
@@ -79,16 +111,22 @@ int main(int argc, char **argv)
}
}
+ if (!log_dir) {
+ log_dir = strdup("/var/log/xen/console");
+ }
+
if (geteuid() != 0) {
fprintf(stderr, "%s requires root to run.\n", argv[0]);
exit(EPERM);
}
+ signal(SIGHUP, handle_hup);
+
openlog("xenconsoled", syslog_option, LOG_DAEMON);
setlogmask(syslog_mask);
if (!is_interactive) {
- daemonize("/var/run/xenconsoled.pid");
+ daemonize(pidfile ? pidfile : "/var/run/xenconsoled.pid");
}
if (!xen_setup())
@@ -99,6 +137,18 @@ int main(int argc, char **argv)
handle_io();
closelog();
+ free(log_dir);
+ free(pidfile);
return 0;
}
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * indent-tabs-mode: t
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
diff -rup xen-3.1.0-src/tools/console/daemon/utils.c xen-3.1.0-src.new/tools/console/daemon/utils.c
--- xen-3.1.0-src/tools/console/daemon/utils.c 2007-05-18 10:45:21.000000000 -0400
+++ xen-3.1.0-src.new/tools/console/daemon/utils.c 2007-06-12 09:28:21.000000000 -0400
@@ -86,7 +86,7 @@ void daemonize(const char *pidfile)
if (chdir("/") < 0)
exit (1);
- fd = open(pidfile, O_RDWR | O_CREAT);
+ fd = open(pidfile, O_RDWR | O_CREAT, S_IRUSR|S_IWUSR);
if (fd == -1) {
exit(1);
}