Patchwork [V2] Support logging xen-guest console

login
register
mail settings
Submitter Chunyan Liu
Date June 22, 2011, 7:26 a.m.
Message ID <1308727563-11572-1-git-send-email-cyliu@novell.com>
Download mbox | patch
Permalink /patch/101400/
State New
Headers show

Comments

Chunyan Liu - June 22, 2011, 7:26 a.m.
Add code to support logging xen-domU console, as what xenconsoled does. Log info
will be saved in /var/log/xen/console/guest-domUname.log.

Signed-off-by: Chunyan Liu <cyliu@novell.com>
---
 hw/xen_console.c |   71 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 71 insertions(+), 0 deletions(-)
Stefano Stabellini - June 22, 2011, 5:40 p.m.
On Wed, 22 Jun 2011, Chunyan Liu wrote:
> Add code to support logging xen-domU console, as what xenconsoled does. Log info
> will be saved in /var/log/xen/console/guest-domUname.log.
> 

I think is OK.
Only one more thing: please make sure your lines don't go over 80
characters.
Anthony Liguori - June 22, 2011, 6:22 p.m.
On 06/22/2011 02:26 AM, Chunyan Liu wrote:
> Add code to support logging xen-domU console, as what xenconsoled does. Log info
> will be saved in /var/log/xen/console/guest-domUname.log.

It needs to be specified by command line.  It's not appropriate to 
assume qemu is running as root with access to a non-user directory.

Regards,

Anthony Liguori

>
> Signed-off-by: Chunyan Liu<cyliu@novell.com>
> ---
>   hw/xen_console.c |   71 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
>   1 files changed, 71 insertions(+), 0 deletions(-)
>
> diff --git a/hw/xen_console.c b/hw/xen_console.c
> index c6c8163..f898e4f 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,15 @@ 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 +201,43 @@ static void xencons_send(struct XenConsole *con)
>       }
>   }
>
> +static int create_domain_log(struct XenConsole *con)
> +{
> +    char *logfile;
> +    char *path, *domname;
> +    int fd;
> +    const char *logdir = "/var/log/xen/console";
> +
> +    path = xs_get_domain_path(xenstore, con->xendev.dom);
> +    domname = xenstore_read_str(path, "name");
> +    free(path);
> +    if (!domname)
> +        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 +256,10 @@ 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 +292,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 +310,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)
Chunyan Liu - June 30, 2011, 7:07 a.m.
On Thursday, June 23, 2011 02:22:37 AM Anthony Liguori wrote:
> On 06/22/2011 02:26 AM, Chunyan Liu wrote:
> > Add code to support logging xen-domU console, as what xenconsoled does.
> > Log info will be saved in /var/log/xen/console/guest-domUname.log.
> 
> It needs to be specified by command line.  It's not appropriate to
> assume qemu is running as root with access to a non-user directory.

Sorry, I'm late to reply. I just come back from vocation. Thanks for your 
remindness. But I think adding a command line option to qemu seems not proper, 
after all, it's a function to xen only. Like XENCONSOLED_TRACE, use 
XENCONSOLED_LOGDIR environment variable instead. Will post V3.

Thanks,
Chunyan

> Regards,
> 
> Anthony Liguori
> 
> > Signed-off-by: Chunyan Liu<cyliu@novell.com>
> > ---
> > 
> >   hw/xen_console.c |   71
> >   ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files
> >   changed, 71 insertions(+), 0 deletions(-)
> > 
> > diff --git a/hw/xen_console.c b/hw/xen_console.c
> > index c6c8163..f898e4f 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,15 @@ 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 +201,43 @@ static void xencons_send(struct XenConsole *con)
> > 
> >       }
> >   
> >   }
> > 
> > +static int create_domain_log(struct XenConsole *con)
> > +{
> > +    char *logfile;
> > +    char *path, *domname;
> > +    int fd;
> > +    const char *logdir = "/var/log/xen/console";
> > +
> > +    path = xs_get_domain_path(xenstore, con->xendev.dom);
> > +    domname = xenstore_read_str(path, "name");
> > +    free(path);
> > +    if (!domname)
> > +        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 +256,10 @@ 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 +292,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 +310,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)

Patch

diff --git a/hw/xen_console.c b/hw/xen_console.c
index c6c8163..f898e4f 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,15 @@  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 +201,43 @@  static void xencons_send(struct XenConsole *con)
     }
 }
 
+static int create_domain_log(struct XenConsole *con)
+{
+    char *logfile;
+    char *path, *domname;
+    int fd;
+    const char *logdir = "/var/log/xen/console";
+
+    path = xs_get_domain_path(xenstore, con->xendev.dom);
+    domname = xenstore_read_str(path, "name");
+    free(path);
+    if (!domname)
+        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 +256,10 @@  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 +292,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 +310,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)