[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] Add persistent guest & hv logging in xenconsoled.
# HG changeset patch # User kfraser@xxxxxxxxxxxxxxxxxxxxx # Date 1180964952 -3600 # Node ID edf407a3dd70db0af60617b6c90aa3589d7c1c7d # Parent da3185b03113611fd322e439f17103af4d11b064 Add persistent guest & hv logging in xenconsoled. * The --log command line argument takes one of 4 values - none - no logging (the default) - hv - log all hypervisor messages - guest - log all guest messages - both - log all guest & hypervisor messages * The --log-dir command line argument takes a path to specify where to store logfiles. If omitted it defaults to /var/log/xen/console * The hypervisor logfile is $LOGDIR/hypervisor.log * The guest logfile is $LOGDIR/guest-[NAME].log * If receiving a SIGHUP it will close & re-open all log files to enable logrotate to do its magic * Fixes the permissions of /var/run/xenconsoled.pid * Adds a --pid-file command line argument to override the default location of pid file (this is not really related to logging, but since I was in that code...) Signed-off-by: Daniel P. Berrange <berrange@xxxxxxxxxx> --- tools/console/daemon/io.c | 154 ++++++++++++++++++++++++++++++++++++++++++- tools/console/daemon/main.c | 54 ++++++++++++++- tools/console/daemon/utils.c | 2 3 files changed, 204 insertions(+), 6 deletions(-) diff -r da3185b03113 -r edf407a3dd70 tools/console/daemon/io.c --- a/tools/console/daemon/io.c Mon Jun 04 14:40:12 2007 +0100 +++ b/tools/console/daemon/io.c Mon Jun 04 14:49:12 2007 +0100 @@ -43,6 +43,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; @@ -56,6 +64,7 @@ struct domain { int domid; int tty_fd; + int log_fd; bool is_dead; struct buffer buffer; struct domain *next; @@ -102,6 +111,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. */ @@ -142,6 +164,53 @@ 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; + } + 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) { @@ -324,6 +393,9 @@ static int domain_create_ring(struct dom } } + if (log_guest) + dom->log_fd = create_domain_log(dom); + out: return err; } @@ -351,6 +423,7 @@ static bool watch_domain(struct domain * return success; } + static struct domain *create_domain(int domid) { struct domain *dom; @@ -382,6 +455,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; @@ -442,6 +517,10 @@ static void cleanup_domain(struct domain if (d->tty_fd != -1) { 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); @@ -604,13 +683,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); @@ -636,7 +756,30 @@ 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 (ret == -1) { + if (errno == EINTR) { + if (log_reload) { + handle_log_reload(); + log_reload = 0; + } + continue; + } + dolog(LOG_ERR, "Failure in select: %d (%s)", + errno, strerror(errno)); + break; + } + + /* Check for timeout */ + if (ret == 0) { + if (log_hv_fd != -1) + handle_hv_logs(); + continue; + } if (FD_ISSET(xs_fileno(xs), &readfds)) handle_xs(); @@ -656,7 +799,12 @@ void handle_io(void) if (d->is_dead) cleanup_domain(d); } - } while (ret > -1); + } + + if (log_hv_fd != -1) + close(log_hv_fd); + if (xc_handle != -1) + xc_interface_close(xc_handle); } /* diff -r da3185b03113 -r edf407a3dd70 tools/console/daemon/main.c --- a/tools/console/daemon/main.c Mon Jun 04 14:40:12 2007 +0100 +++ b/tools/console/daemon/main.c Mon Jun 04 14:49:12 2007 +0100 @@ -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 -r da3185b03113 -r edf407a3dd70 tools/console/daemon/utils.c --- a/tools/console/daemon/utils.c Mon Jun 04 14:40:12 2007 +0100 +++ b/tools/console/daemon/utils.c Mon Jun 04 14:49:12 2007 +0100 @@ -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); } _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |