WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] [xen-unstable] Add persistent guest & hv logging in xenc

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] Add persistent guest & hv logging in xenconsoled.
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Mon, 11 Jun 2007 02:22:09 -0700
Delivery-date: Mon, 11 Jun 2007 02:23:38 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# 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

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] Add persistent guest & hv logging in xenconsoled., Xen patchbot-unstable <=