From patchwork Thu Jun 30 07:08:42 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chunyan Liu X-Patchwork-Id: 102712 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [140.186.70.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id C2C0AB6F5C for ; Thu, 30 Jun 2011 17:12:40 +1000 (EST) Received: from localhost ([::1]:45770 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1QcBQT-0004n1-G6 for incoming@patchwork.ozlabs.org; Thu, 30 Jun 2011 03:12:37 -0400 Received: from eggs.gnu.org ([140.186.70.92]:48735) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1QcBNO-0004mO-E9 for qemu-devel@nongnu.org; Thu, 30 Jun 2011 03:09:27 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1QcBNM-0002fH-Ul for qemu-devel@nongnu.org; Thu, 30 Jun 2011 03:09:26 -0400 Received: from victor.provo.novell.com ([137.65.250.26]:41399) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1QcBNM-0002fC-Gj for qemu-devel@nongnu.org; Thu, 30 Jun 2011 03:09:24 -0400 Received: from localhost.localdomain (prv-ext-foundry1int.gns.novell.com [137.65.251.240]) by victor.provo.novell.com with ESMTP (TLS encrypted); Thu, 30 Jun 2011 01:09:21 -0600 From: Chunyan Liu To: qemu-devel@nongnu.org, Stefano.Stabellini@eu.citrix.com, anthony@codemonkey.ws Date: Thu, 30 Jun 2011 15:08:42 +0800 Message-Id: <1309417722-11424-1-git-send-email-cyliu@novell.com> X-Mailer: git-send-email 1.7.3.4 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6, seldom 2.4 (older, 4) X-Received-From: 137.65.250.26 Subject: [Qemu-devel] [PATCH V3] Support logging xen-guest console X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Add code to support logging xen-domU console, as what xenconsoled does. To enable logging, set environment variable XENCONSOLED_TRACE=guest and XENCONSOLED_LOGDIR=, log file will be saved in . Signed-off-by: Chunyan Liu --- hw/xen_console.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 82 insertions(+), 0 deletions(-) diff --git a/hw/xen_console.c b/hw/xen_console.c index c6c8163..51e2ba2 100644 --- a/hw/xen_console.c +++ b/hw/xen_console.c @@ -36,6 +36,8 @@ #include "qemu-char.h" #include "xen_backend.h" +static int log_guest = 0; + struct buffer { uint8_t *data; size_t consumed; @@ -52,8 +54,24 @@ struct XenConsole { void *sring; CharDriverState *chr; int backlog; + int log_fd; }; +static int write_all(int fd, const char* buf, size_t len) +{ + while (len) { + ssize_t ret = write(fd, buf, len); + if (ret == -1 && errno == EINTR) + continue; + if (ret < 0) + return -1; + len -= ret; + buf += ret; + } + + return 0; +} + static void buffer_append(struct XenConsole *con) { struct buffer *buffer = &con->buffer; @@ -81,6 +99,17 @@ static void buffer_append(struct XenConsole *con) intf->out_cons = cons; xen_be_send_notify(&con->xendev); + if (con->log_fd != -1) { + int logret; + logret = write_all(con->log_fd, + buffer->data + buffer->size - size, size); + if (logret < 0) { + xen_be_printf(&con->xendev, 1, + "Write to log failed on domain %d: %d (%s)\n", + con->xendev.dom, errno, strerror(errno)); + } + } + if (buffer->max_capacity && buffer->size > buffer->max_capacity) { /* Discard the middle of the data. */ @@ -174,12 +203,51 @@ static void xencons_send(struct XenConsole *con) } } +static int create_domain_log(struct XenConsole *con) +{ + char *logfile; + char *path, *domname; + int fd; + char *logdir; + + path = xs_get_domain_path(xenstore, con->xendev.dom); + domname = xenstore_read_str(path, "name"); + free(path); + if (!domname) + return -1; + + logdir = getenv("XENCONSOLED_LOGDIR"); + if (!logdir) + return -1; + if (mkdir(logdir, 0755) && errno != EEXIST) + { + xen_be_printf(&con->xendev, 1, + "Directory %s does not exist and fail to create it!", + logdir); + return -1; + } + + asprintf(&logfile, "%s/guest-%s.log", logdir, domname); + qemu_free(domname); + + fd = open(logfile, O_WRONLY|O_CREAT|O_APPEND, 0644); + free(logfile); + if (fd == -1) { + xen_be_printf(&con->xendev, 1, + "Failed to open log %s: %d (%s)", + logfile, errno, strerror(errno)); + } + + return fd; +} + /* -------------------------------------------------------------------- */ static int con_init(struct XenDevice *xendev) { struct XenConsole *con = container_of(xendev, struct XenConsole, xendev); char *type, *dom; + char *logenv = NULL; /* setup */ dom = xs_get_domain_path(xenstore, con->xendev.dom); @@ -198,6 +266,11 @@ static int con_init(struct XenDevice *xendev) else con->chr = serial_hds[con->xendev.dev]; + logenv = getenv("XENCONSOLED_TRACE"); + if (logenv != NULL && strlen(logenv) == strlen("guest") + && !strcmp(logenv, "guest")) { + log_guest = 1; + } return 0; } @@ -230,6 +303,9 @@ static int con_connect(struct XenDevice *xendev) con->xendev.remote_port, con->xendev.local_port, con->buffer.max_capacity); + con->log_fd = -1; + if (log_guest) + con->log_fd = create_domain_log(con); return 0; } @@ -245,6 +321,12 @@ static void con_disconnect(struct XenDevice *xendev) munmap(con->sring, XC_PAGE_SIZE); con->sring = NULL; } + + if (con->log_fd != -1) { + close(con->log_fd); + con->log_fd = -1; + } + } static void con_event(struct XenDevice *xendev)