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