[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH 05 of 21 RESEND] blktap3/drivers: Introduce logging for the tapdisk



This patch copies logging functionality from blktap2, with changes coming from
blktap2.5.

Signed-off-by: Thanos Makatos <thanos.makatos@xxxxxxxxxx>

diff --git a/tools/blktap2/drivers/log.h b/tools/blktap3/drivers/log.h
copy from tools/blktap2/drivers/log.h
copy to tools/blktap3/drivers/log.h
--- a/tools/blktap2/drivers/log.h
+++ b/tools/blktap3/drivers/log.h
@@ -32,10 +32,7 @@
 #define __LOG_H__ 1
 
 #include <inttypes.h>
-
 #include <xen/io/ring.h>
-/* for wmb et al */
-#include <xenctrl.h>
 
 #define LOGCMD_SHMP  "shmp"
 #define LOGCMD_PEEK  "peek"
diff --git a/tools/blktap2/drivers/tapdisk-client.c 
b/tools/blktap3/drivers/tapdisk-client.c
copy from tools/blktap2/drivers/tapdisk-client.c
copy to tools/blktap3/drivers/tapdisk-client.c
--- a/tools/blktap2/drivers/tapdisk-client.c
+++ b/tools/blktap3/drivers/tapdisk-client.c
@@ -39,6 +39,7 @@
 #include <sys/socket.h>
 #include <sys/types.h>
 #include <sys/un.h>
+#include <xenctrl.h>
 
 #include "log.h"
 
@@ -109,7 +110,7 @@ static int tdctl_open(const char* sockpa
   saddr.sun_family = AF_UNIX;
   memcpy(saddr.sun_path, sockpath, strlen(sockpath));
 
-  if (connect(fd, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) {
+  if (connect(fd, &saddr, sizeof(saddr)) < 0) {
     BWPRINTF("error connecting to socket %s: %s", sockpath, strerror(errno));
     close(fd);
     return -1;
@@ -392,7 +393,7 @@ int await_responses(struct writelog* wl,
     BWPRINTF("EOF on control socket");
     return -1;
   } else if (rc < sizeof(msg)) {
-         BWPRINTF("short reply (%d/%d bytes)", rc, (int) sizeof(msg));
+         BWPRINTF("short reply (%d/%lu bytes)", rc, sizeof(msg));
     return -1;
   }
 
diff --git a/tools/blktap2/drivers/tapdisk-log.c 
b/tools/blktap3/drivers/tapdisk-log.c
copy from tools/blktap2/drivers/tapdisk-log.c
copy to tools/blktap3/drivers/tapdisk-log.c
--- a/tools/blktap2/drivers/tapdisk-log.c
+++ b/tools/blktap3/drivers/tapdisk-log.c
@@ -1,5 +1,5 @@
 /* 
- * Copyright (c) 2008, XenSource Inc.
+ * Copyright (c) 2008, 2009, XenSource Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -26,232 +26,241 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
-#include <stdio.h>
-#include <fcntl.h>
+#include <stdlib.h>
 #include <unistd.h>
-#include <stdlib.h>
-#include <string.h>
+#include <errno.h>
 #include <stdarg.h>
 #include <syslog.h>
-#include <inttypes.h>
 #include <sys/time.h>
+#include <sys/stat.h>
+#include <sys/types.h>
 
 #include "tapdisk-log.h"
 #include "tapdisk-utils.h"
+#include "tapdisk-logfile.h"
+#include "tapdisk-syslog.h"
+#include "tapdisk-server.h"
+
+#define TLOG_LOGFILE_BUFSZ (16<<10)
+#define TLOG_SYSLOG_BUFSZ   (8<<10)
 
 #define MAX_ENTRY_LEN      512
-#define MAX_ERROR_MESSAGES 16
 
-struct error {
-       int            cnt;
-       int            err;
-       char          *func;
-       char           msg[MAX_ENTRY_LEN];
+struct tlog {
+    char *name;
+    td_logfile_t logfile;
+    int precious;
+       int            level;
+
+    char *ident;
+    td_syslog_t syslog;
+    unsigned long errors;
 };
 
-struct ehandle {
-       int            cnt;
-       int            dropped;
-       struct error   errors[MAX_ERROR_MESSAGES];
-};
-
-struct tlog {
-       char          *p;
-       int            size;
-       uint64_t       cnt;
-       char          *buf;
-       int            level;
-       char          *file;
-       int            append;
-};
-
-static struct ehandle tapdisk_err;
 static struct tlog tapdisk_log;
 
-void
-open_tlog(char *file, size_t bytes, int level, int append)
+static void tlog_logfile_vprint(const char *fmt, va_list ap)
 {
-       tapdisk_log.size = ((bytes + 511) & (~511));
+    tapdisk_logfile_vprintf(&tapdisk_log.logfile, fmt, ap);
+}
 
-       if (asprintf(&tapdisk_log.file, "%s.%d", file, getpid()) == -1)
-               return;
+static void __printf(1, 2) tlog_logfile_print(const char *fmt, ...)
+{
+    va_list ap;
 
-       if (posix_memalign((void **)&tapdisk_log.buf, 512, tapdisk_log.size)) {
-               free(tapdisk_log.file);
-               tapdisk_log.buf = NULL;
-               return;
+    va_start(ap, fmt);
+    tlog_logfile_vprint(fmt, ap);
+    va_end(ap);
        }
 
-       memset(tapdisk_log.buf, 0, tapdisk_log.size);
+#define tlog_info(_fmt, _args ...)                                     \
+       tlog_logfile_print("%s: "_fmt, tapdisk_log.ident, ##_args)
 
-       tapdisk_log.p      = tapdisk_log.buf;
-       tapdisk_log.level  = level;
-       tapdisk_log.append = append;
+static void tlog_logfile_save(void)
+{
+    td_logfile_t *logfile = &tapdisk_log.logfile;
+    const char *name = tapdisk_log.name;
+    int err;
+
+    tlog_info("saving log, %lu errors", tapdisk_log.errors);
+
+    tapdisk_logfile_flush(logfile);
+
+    err = tapdisk_logfile_rename(logfile, TLOG_DIR, name, ".log");
+
+    tlog_syslog(LOG_INFO, "logfile saved to %s: %d\n", logfile->path, err);
+}
+
+static void tlog_logfile_close(void)
+{
+    td_logfile_t *logfile = &tapdisk_log.logfile;
+    int keep;
+
+    keep = tapdisk_log.precious || tapdisk_log.errors;
+
+    tlog_info("closing log, %lu errors", tapdisk_log.errors);
+
+    if (keep)
+        tlog_logfile_save();
+
+    tapdisk_logfile_close(logfile);
+
+    if (!keep)
+        tapdisk_logfile_unlink(logfile);
+}
+
+static int tlog_logfile_open(const char *name, int level)
+{
+    td_logfile_t *logfile = &tapdisk_log.logfile;
+    int mode, err;
+
+    err = mkdir(TLOG_DIR, 0755);
+    if (err) {
+        err = -errno;
+        if (err != -EEXIST)
+            goto fail;
+    }
+
+    err = tapdisk_logfile_open(logfile,
+                               TLOG_DIR, name, ".tmp", TLOG_LOGFILE_BUFSZ);
+    if (err)
+        goto fail;
+
+    mode = (level == TLOG_DBG) ? _IOLBF : _IOFBF;
+
+    err = tapdisk_logfile_setvbuf(logfile, mode);
+    if (err)
+        goto fail;
+
+    tlog_info("log start, level %d", level);
+
+    return 0;
+
+  fail:
+    tlog_logfile_close();
+    return err;
+}
+
+static void tlog_syslog_close(void)
+{
+    td_syslog_t *syslog = &tapdisk_log.syslog;
+
+    tapdisk_syslog_stats(syslog, LOG_INFO);
+    tapdisk_syslog_flush(syslog);
+    tapdisk_syslog_close(syslog);
+       }
+
+static int tlog_syslog_open(const char *ident __attribute__((unused)),
+        int facility)
+{
+    td_syslog_t *syslog = &tapdisk_log.syslog;
+    int err;
+
+    err = tapdisk_syslog_open(syslog,
+                              tapdisk_log.ident, facility,
+                              TLOG_SYSLOG_BUFSZ);
+    return err;
+       }
+
+void tlog_vsyslog(int prio, const char *fmt, va_list ap)
+{
+    td_syslog_t *syslog = &tapdisk_log.syslog;
+
+    tapdisk_vsyslog(syslog, prio, fmt, ap);
+}
+
+void tlog_syslog(int prio, const char *fmt, ...)
+{
+    va_list ap;
+
+       va_start(ap, fmt);
+    tlog_vsyslog(prio, fmt, ap);
+       va_end(ap);
+}
+
+int
+tlog_open(const char *name, int facility, int level)
+{
+    int err;
+
+    DPRINTF("tapdisk-log: started, level %d\n", level);
+
+    tapdisk_log.level = level;
+    tapdisk_log.name = strdup(name);
+    tapdisk_log.ident = tapdisk_syslog_ident(name);
+
+    if (!tapdisk_log.name || !tapdisk_log.ident) {
+        err = -errno;
+        goto fail;
+       }
+
+    err = tlog_logfile_open(tapdisk_log.name, level);
+    if (err)
+        goto fail;
+
+    err = tlog_syslog_open(tapdisk_log.ident, facility);
+    if (err)
+        goto fail;
+
+    return 0;
+
+  fail:
+    tlog_close();
+    return err;
 }
 
 void
-close_tlog(void)
+tlog_close(void)
 {
-       if (!tapdisk_log.buf)
-               return;
+    DPRINTF("tapdisk-log: closing after %lu errors\n", tapdisk_log.errors);
 
-       if (tapdisk_log.append)
-               tlog_flush();
+    tlog_logfile_close();
+    tlog_syslog_close();
 
-       free(tapdisk_log.buf);
-       free(tapdisk_log.file);
+    free(tapdisk_log.ident);
+    tapdisk_log.ident = NULL;
+}
 
-       memset(&tapdisk_log, 0, sizeof(struct tlog));
+void tlog_precious(void)
+{
+    if (!tapdisk_log.precious)
+        tlog_logfile_save();
+
+    tapdisk_log.precious = 1;
 }
 
 void
-__tlog_write(int level, const char *func, const char *fmt, ...)
+__tlog_write(int level, const char *fmt, ...)
 {
-       char *buf;
-       va_list ap;
-       struct timeval t;
-       int ret, len, avail;
+    va_list ap;
 
-       if (!tapdisk_log.buf)
-               return;
-
-       if (level > tapdisk_log.level)
-               return;
-
-       avail = tapdisk_log.size - (tapdisk_log.p - tapdisk_log.buf);
-       if (avail < MAX_ENTRY_LEN) {
-               if (tapdisk_log.append)
-                       tlog_flush();
-               tapdisk_log.p = tapdisk_log.buf;
-       }
-
-       buf = tapdisk_log.p;
-       gettimeofday(&t, NULL);
-       len = snprintf(buf, MAX_ENTRY_LEN - 1, "%08"PRIu64":%010ld.%06lld:"
-                      "%s ", tapdisk_log.cnt,
-                       t.tv_sec, (unsigned long long)t.tv_usec, func);
-
-       va_start(ap, fmt);
-       ret = vsnprintf(buf + len, MAX_ENTRY_LEN - (len + 1), fmt, ap);
-       va_end(ap);
-
-       len = (ret < MAX_ENTRY_LEN - (len + 1) ?
-              len + ret : MAX_ENTRY_LEN - 1);
-       buf[len] = '\0';
-
-       tapdisk_log.cnt++;
-       tapdisk_log.p += len;
+    if (level <= tapdisk_log.level) {
+        va_start(ap, fmt);
+        tlog_logfile_vprint(fmt, ap);
+        va_end(ap);
+    }
 }
 
-void
-__tlog_error(int err, const char *func, const char *fmt, ...)
+void __tlog_error(const char *fmt, ...)
 {
-       va_list ap;
-       int i, len, ret;
-       struct error *e;
-       struct timeval t;
+    va_list ap;
 
-       err = (err > 0 ? err : -err);
+    va_start(ap, fmt);
+    tlog_vsyslog(LOG_ERR, fmt, ap);
+    va_end(ap);
 
-       for (i = 0; i < tapdisk_err.cnt; i++) {
-               e = &tapdisk_err.errors[i];
-               if (e->err == err && e->func == func) {
-                       e->cnt++;
-                       return;
-               }
-       }
-
-       if (tapdisk_err.cnt >= MAX_ERROR_MESSAGES) {
-               tapdisk_err.dropped++;
-               return;
-       }
-
-       gettimeofday(&t, NULL);
-       e = &tapdisk_err.errors[tapdisk_err.cnt];
-
-       len = snprintf(e->msg, MAX_ENTRY_LEN - 1, "%010ld.%06lld:%s ",
-                      t.tv_sec, (unsigned long long)t.tv_usec, func);
-
-       va_start(ap, fmt);
-       ret = vsnprintf(e->msg + len, MAX_ENTRY_LEN - (len + 1), fmt, ap);
-       va_end(ap);
-
-       len = (ret < MAX_ENTRY_LEN - (len + 1) ?
-              len + ret : MAX_ENTRY_LEN - 1);
-       e->msg[len] = '\0';
-
-       e->cnt++;
-       e->err  = err;
-       e->func = (char *)func;
-       tapdisk_err.cnt++;
+    tapdisk_log.errors++;
 }
 
-void
-tlog_print_errors(void)
+void tapdisk_start_logging(const char *ident, const char *_facility)
 {
-       int i;
-       struct error *e;
+    int facility;
 
-       for (i = 0; i < tapdisk_err.cnt; i++) {
-               e = &tapdisk_err.errors[i];
-               syslog(LOG_INFO, "TAPDISK ERROR: errno %d at %s (cnt = %d): "
-                      "%s\n", e->err, e->func, e->cnt, e->msg);
-       }
-
-       if (tapdisk_err.dropped)
-               syslog(LOG_INFO, "TAPDISK ERROR: %d other error messages "
-                      "dropped\n", tapdisk_err.dropped);
+    facility = tapdisk_syslog_facility(_facility);
+    tapdisk_server_openlog(ident, LOG_CONS | LOG_ODELAY, facility);
 }
 
-void
-tlog_flush_errors(void)
+void tapdisk_stop_logging(void)
 {
-       int i;
-       struct error *e;
-
-       for (i = 0; i < tapdisk_err.cnt; i++) {
-               e = &tapdisk_err.errors[i];
-               tlog_write(TLOG_WARN, "TAPDISK ERROR: errno %d at %s "
-                          "(cnt = %d): %s\n", e->err, e->func, e->cnt,
-                          e->msg);
-       }
-
-       if (tapdisk_err.dropped)
-               tlog_write(TLOG_WARN, "TAPDISK ERROR: %d other error messages "
-                      "dropped\n", tapdisk_err.dropped);
+    tapdisk_server_closelog();
 }
-
-void
-tlog_flush(void)
-{
-       int fd, flags;
-       size_t size, wsize;
-
-       if (!tapdisk_log.buf)
-               return;
-
-       flags = O_CREAT | O_WRONLY | O_DIRECT | O_NONBLOCK;
-       if (!tapdisk_log.append)
-               flags |= O_TRUNC;
-
-       fd = open(tapdisk_log.file, flags, 0644);
-       if (fd == -1)
-               return;
-
-       if (tapdisk_log.append)
-               if (lseek(fd, 0, SEEK_END) == (off_t)-1)
-                       goto out;
-
-       tlog_flush_errors();
-
-       size  = tapdisk_log.p - tapdisk_log.buf;
-       wsize = ((size + 511) & (~511));
-
-       memset(tapdisk_log.buf + size, '\n', wsize - size);
-       write_exact(fd, tapdisk_log.buf, wsize);
-
-       tapdisk_log.p = tapdisk_log.buf;
-
-out:
-       close(fd);
-}
diff --git a/tools/blktap3/drivers/tapdisk-logfile.c 
b/tools/blktap3/drivers/tapdisk-logfile.c
new file mode 100644
--- /dev/null
+++ b/tools/blktap3/drivers/tapdisk-logfile.c
@@ -0,0 +1,246 @@
+/*
+ * Copyright (c) 2009, XenSource Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of XenSource Inc. nor the names of its contributors
+ *       may be used to endorse or promote products derived from this software
+ *       without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <time.h>
+#include <stdarg.h>
+#include <sys/time.h>
+#include <sys/mman.h>
+
+#include "tapdisk-logfile.h"
+#include "tapdisk-utils.h"
+
+#define MIN(a,b) (((a) < (b)) ? (a) : (b))
+
+static inline size_t page_align(size_t size)
+{
+    size_t page_size = sysconf(_SC_PAGE_SIZE);
+    return (size + page_size - 1) & ~(page_size - 1);
+}
+
+static void tapdisk_logfile_free_buffer(td_logfile_t * log)
+{
+    if (log->vbuf) {
+        munmap(log->vbuf, page_align(log->vbufsz));
+        log->vbuf = NULL;
+    }
+}
+
+static int tapdisk_logfile_init_buffer(td_logfile_t * log, size_t size)
+{
+    int prot, flags, err;
+
+    if (!size)
+        return -EINVAL;
+
+    prot = PROT_READ | PROT_WRITE;
+    flags = MAP_ANONYMOUS | MAP_PRIVATE;
+
+    log->vbuf = mmap(NULL, page_align(size), prot, flags, -1, 0);
+    if (log->vbuf == MAP_FAILED) {
+        log->vbuf = NULL;
+        goto fail;
+    }
+
+    err = mlock(log->vbuf, page_align(size));
+    if (err)
+        goto fail;
+
+    log->vbufsz = size;
+
+    return 0;
+
+  fail:
+    tapdisk_logfile_free_buffer(log);
+    err = -errno;
+    return err;
+}
+
+int tapdisk_logfile_unlink(td_logfile_t * log)
+{
+    int err;
+
+    err = unlink(log->path);
+    if (err)
+        err = -errno;
+
+    return err;
+}
+
+static int
+__tapdisk_logfile_rename(td_logfile_t * log, const char *newpath)
+{
+    const size_t max = sizeof(log->path);
+    int err;
+
+    if (!strcmp(log->path, newpath))
+        return 0;
+
+    if (strlen(newpath) > max)
+        return -ENAMETOOLONG;
+
+    err = rename(log->path, newpath);
+    if (err) {
+        err = -errno;
+        return err;
+    }
+
+    strncpy(log->path, newpath, max);
+
+    return 0;
+}
+
+static int
+tapdisk_logfile_name(char *path, size_t size,
+                     const char *dir, const char *ident,
+                     const char *suffix)
+{
+    const size_t max = MIN(size, TD_LOGFILE_PATH_MAX);
+    return snprintf(path, max, "%s/%s.%d%s", dir, ident, getpid(), suffix);
+}
+
+int
+tapdisk_logfile_rename(td_logfile_t * log,
+                       const char *dir, const char *ident,
+                       const char *suffix)
+{
+    char newpath[TD_LOGFILE_PATH_MAX + 1];
+
+    tapdisk_logfile_name(newpath, sizeof(newpath), dir, ident, suffix);
+
+    return __tapdisk_logfile_rename(log, newpath);
+}
+
+void tapdisk_logfile_close(td_logfile_t * log)
+{
+    if (log->file) {
+        fclose(log->file);
+        log->file = NULL;
+    }
+
+    tapdisk_logfile_free_buffer(log);
+}
+
+int
+tapdisk_logfile_open(td_logfile_t * log,
+                     const char *dir, const char *ident, const char *ext,
+                     size_t bufsz)
+{
+    int err;
+
+    memset(log, 0, sizeof(log));
+
+    tapdisk_logfile_name(log->path, sizeof(log->path), dir, ident, ext);
+
+    log->file = fopen(log->path, "w");
+    if (!log->file) {
+        err = -errno;
+        goto fail;
+    }
+
+    err = tapdisk_logfile_init_buffer(log, bufsz);
+    if (err)
+        goto fail;
+
+    return 0;
+
+  fail:
+    tapdisk_logfile_unlink(log);
+    tapdisk_logfile_close(log);
+    return err;
+}
+
+int tapdisk_logfile_setvbuf(td_logfile_t * log, int mode)
+{
+    int err = 0;
+
+    if (log->file) {
+        err = setvbuf(log->file, log->vbuf, mode, log->vbufsz);
+        if (err)
+            err = -errno;
+    }
+
+    return err;
+}
+
+ssize_t
+tapdisk_logfile_vprintf(td_logfile_t * log, const char *fmt, va_list ap)
+{
+    char buf[1024];
+    size_t size, n;
+    ssize_t len;
+    struct timeval tv;
+
+    if (!log->file)
+        return -EBADF;
+
+    gettimeofday(&tv, NULL);
+
+    size = sizeof(buf);
+    len = 0;
+
+    len += tapdisk_syslog_strftime(buf, size, &tv);
+    len += snprintf(buf + len, size - len, ": ");
+    len += tapdisk_syslog_strftv(buf + len, size - len, &tv);
+    len += snprintf(buf + len, size - len, " ");
+    len += vsnprintf(buf + len, size - len, fmt, ap);
+
+    if (buf[len - 1] != '\n')
+        len += snprintf(buf + len, size - len, "\n");
+
+    n = fwrite(buf, len, 1, log->file);
+    if (n != len)
+        len = -ferror(log->file);
+
+    return len;
+}
+
+ssize_t tapdisk_logfile_printf(td_logfile_t * log, const char *fmt, ...)
+{
+    va_list ap;
+    int rv;
+
+    va_start(ap, fmt);
+    rv = tapdisk_logfile_vprintf(log, fmt, ap);
+    va_end(ap);
+
+    return rv;
+}
+
+int tapdisk_logfile_flush(td_logfile_t * log)
+{
+    int rv = EOF;
+
+    if (log->file)
+        rv = fflush(log->file);
+
+    return rv;
+}
diff --git a/tools/blktap3/drivers/tapdisk-logfile.h 
b/tools/blktap3/drivers/tapdisk-logfile.h
new file mode 100644
--- /dev/null
+++ b/tools/blktap3/drivers/tapdisk-logfile.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2009, XenSource Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of XenSource Inc. nor the names of its contributors
+ *       may be used to endorse or promote products derived from this software
+ *       without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __TAPDISK_LOGFILE_H__
+#define __TAPDISK_LOGFILE_H__
+
+#include <stdio.h>
+
+typedef struct _td_logfile td_logfile_t;
+
+#define TD_LOGFILE_PATH_MAX    128UL
+
+struct _td_logfile {
+    char path[TD_LOGFILE_PATH_MAX];
+    FILE *file;
+    char *vbuf;
+    size_t vbufsz;
+};
+
+int tapdisk_logfile_open(td_logfile_t *,
+                         const char *dir, const char *ident,
+                         const char *ext, size_t bufsz);
+
+ssize_t tapdisk_logfile_printf(td_logfile_t *, const char *fmt, ...);
+ssize_t tapdisk_logfile_vprintf(td_logfile_t *, const char *fmt,
+                                va_list ap);
+
+void tapdisk_logfile_close(td_logfile_t *);
+int tapdisk_logfile_unlink(td_logfile_t *);
+int tapdisk_logfile_rename(td_logfile_t *,
+                           const char *dir, const char *ident,
+                           const char *ext);
+
+int tapdisk_logfile_setvbuf(td_logfile_t * log, int mode);
+int tapdisk_logfile_flush(td_logfile_t *);
+
+#endif                          /* __TAPDISK_LOGFILE_H__ */
diff --git a/tools/blktap3/drivers/tapdisk-loglimit.c 
b/tools/blktap3/drivers/tapdisk-loglimit.c
new file mode 100644
--- /dev/null
+++ b/tools/blktap3/drivers/tapdisk-loglimit.c
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2011, XenSource Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of XenSource Inc. nor the names of its contributors
+ *       may be used to endorse or promote products derived from this software
+ *       without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Simple log rate limiting. Allow for bursts, then drop messages
+ * until some interval expired.
+ */
+
+#include <stdio.h>
+#include "blktap3.h"
+#include "tapdisk-loglimit.h"
+
+void tapdisk_loglimit_init(td_loglimit_t * rl, int burst, int interval)
+{
+    rl->burst = burst;
+    rl->interval = interval;
+
+    rl->count = 0;
+    rl->dropped = 0;
+
+    gettimeofday(&rl->ts, NULL);
+}
+
+static void timeradd_ms(struct timeval *tv, long ms)
+{
+    tv->tv_usec += ms * 1000;
+    if (tv->tv_usec > 1000000) {
+        tv->tv_sec += tv->tv_usec / 1000000;
+        tv->tv_usec %= 1000000;
+    }
+}
+
+static void
+tapdisk_loglimit_update(td_loglimit_t * rl, struct timeval *now)
+{
+    struct timeval next = rl->ts;
+
+    timeradd_ms(&next, rl->interval);
+
+    if (timercmp(&next, now, <)) {
+        rl->count = 0;
+        rl->ts = *now;
+    }
+}
+
+static void tapdisk_loglimit_update_now(td_loglimit_t * rl)
+{
+    struct timeval now;
+
+    gettimeofday(&now, NULL);
+
+    tapdisk_loglimit_update(rl, &now);
+}
+
+int tapdisk_loglimit_pass(td_loglimit_t * rl)
+{
+    if (!rl->interval)
+        return 1;               /* unlimited */
+
+    if (unlikely(rl->count >= rl->burst)) {
+
+        tapdisk_loglimit_update_now(rl);
+
+        if (rl->count >= rl->burst) {
+            rl->dropped++;
+            return 0;
+        }
+    }
+
+    rl->count++;
+    return 1;
+}
diff --git a/tools/blktap3/drivers/tapdisk-loglimit.h 
b/tools/blktap3/drivers/tapdisk-loglimit.h
new file mode 100644
--- /dev/null
+++ b/tools/blktap3/drivers/tapdisk-loglimit.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2011, XenSource Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of XenSource Inc. nor the names of its contributors
+ *       may be used to endorse or promote products derived from this software
+ *       without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __TAPDISK_LOGLIMIT_H__
+#define __TAPDISK_LOGLIMIT_H__
+
+#include <sys/time.h>
+
+typedef struct td_loglimit td_loglimit_t;
+
+struct td_loglimit {
+    int burst;
+    int interval;
+
+    int count;
+    int dropped;
+
+    struct timeval ts;
+};
+
+void tapdisk_loglimit_init(td_loglimit_t * rl, int burst, int interval);
+
+int tapdisk_loglimit_pass(td_loglimit_t *);
+
+#endif                          /* __TAPDISK_LOGLIMIT_H__ */
diff --git a/tools/blktap3/drivers/tapdisk-syslog.c 
b/tools/blktap3/drivers/tapdisk-syslog.c
new file mode 100644
--- /dev/null
+++ b/tools/blktap3/drivers/tapdisk-syslog.c
@@ -0,0 +1,544 @@
+/*
+ * Copyright (c) 2009, XenSource Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of XenSource Inc. nor the names of its contributors
+ *       may be used to endorse or promote products derived from this software
+ *       without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * A non-blocking, buffered BSD syslog client.
+ *
+ * http://www.ietf.org/rfc/rfc3164.txt (FIXME: Read this.)
+ */
+
+#define _ISOC99_SOURCE
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <unistd.h>
+#include <time.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <sys/mman.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/param.h>
+
+#include "tapdisk-server.h"
+#include "tapdisk-syslog.h"
+#include "tapdisk-utils.h"
+
+static int tapdisk_syslog_sock_send(td_syslog_t * log,
+                                    const void *msg, size_t size);
+static int tapdisk_syslog_sock_connect(td_syslog_t * log);
+
+static void tapdisk_syslog_sock_mask(td_syslog_t * log);
+static void tapdisk_syslog_sock_unmask(td_syslog_t * log);
+
+static const struct sockaddr_un syslog_addr = {
+    .sun_family = AF_UNIX,
+    .sun_path = "/dev/log"
+};
+
+#define RING_PTR(_log, _idx)                                            \
+       (&(_log)->ring[(_idx) % (_log)->ringsz])
+
+#define RING_FREE(_log)                                                 \
+       ((_log)->ringsz - ((_log)->prod - (_log)->cons))
+
+/*
+ * NB. Ring buffer.
+ *
+ * We allocate a number of pages as indicated by @bufsz during
+ * initialization. From that, 1K is reserved for message staging, the
+ * rest is cyclic ring space.
+ *
+ * All producer/consumer offsets wrap on size_t range, not buffer
+ * size. Hence the RING() macros.
+ */
+
+static void __tapdisk_syslog_ring_init(td_syslog_t * log)
+{
+    log->buf = NULL;
+    log->bufsz = 0;
+    log->msg = NULL;
+    log->ring = NULL;
+    log->ringsz = 0;
+}
+
+static inline size_t page_align(size_t size)
+{
+    size_t page_size = sysconf(_SC_PAGE_SIZE);
+    return (size + page_size - 1) & ~(page_size - 1);
+}
+
+static void tapdisk_syslog_ring_uninit(td_syslog_t * log)
+{
+    if (log->buf)
+        munmap(log->buf, log->bufsz);
+
+    __tapdisk_syslog_ring_init(log);
+}
+
+static int tapdisk_syslog_ring_init(td_syslog_t * log, size_t size)
+{
+    int prot, flags, err;
+
+    __tapdisk_syslog_ring_init(log);
+
+    log->bufsz = page_align(size);
+
+    prot = PROT_READ | PROT_WRITE;
+    flags = MAP_ANONYMOUS | MAP_PRIVATE;
+
+    log->buf = mmap(NULL, log->bufsz, prot, flags, -1, 0);
+    if (log->buf == MAP_FAILED) {
+        log->buf = NULL;
+        err = -ENOMEM;
+        goto fail;
+    }
+
+    err = mlock(log->buf, size);
+    if (err) {
+        err = -errno;
+        goto fail;
+    }
+
+    log->msg = log->buf;
+    log->ring = log->buf + TD_SYSLOG_PACKET_MAX;
+    log->ringsz = size - TD_SYSLOG_PACKET_MAX;
+
+    return 0;
+
+  fail:
+    tapdisk_syslog_ring_uninit(log);
+
+    return err;
+}
+
+static int
+tapdisk_syslog_ring_write_str(td_syslog_t * log, const char *msg,
+                              size_t len)
+{
+    size_t size, prod, i;
+
+    len = MIN(len, TD_SYSLOG_PACKET_MAX);
+    size = len + 1;
+
+    if (size > RING_FREE(log))
+        return -ENOBUFS;
+
+    prod = log->prod;
+
+    for (i = 0; i < len; ++i) {
+        char c;
+
+        c = msg[i];
+        if (c == 0)
+            break;
+
+        *RING_PTR(log, prod) = c;
+        prod++;
+    }
+
+    *RING_PTR(log, prod) = 0;
+
+    log->prod = prod + 1;
+
+    return 0;
+}
+
+static ssize_t
+tapdisk_syslog_ring_read_pkt(td_syslog_t * log, char *msg, size_t size)
+{
+    size_t cons;
+    ssize_t sz;
+
+    size = MIN(size, TD_SYSLOG_PACKET_MAX);
+
+    sz = 0;
+    cons = log->cons;
+
+    while (sz < size) {
+        char c;
+
+        if (cons == log->prod)
+            break;
+
+        c = *RING_PTR(log, cons);
+        msg[sz++] = c;
+        cons++;
+
+        if (c == 0)
+            break;
+    }
+
+    return sz - 1;
+}
+
+static int tapdisk_syslog_ring_dispatch_one(td_syslog_t * log)
+{
+    size_t len;
+    int err;
+
+    len = tapdisk_syslog_ring_read_pkt(log, log->msg,
+                                       TD_SYSLOG_PACKET_MAX);
+    if (len == -1)
+        return -ENOMSG;
+
+    err = tapdisk_syslog_sock_send(log, log->msg, len);
+
+    if (err == -EAGAIN)
+        return err;
+
+    if (err)
+        goto fail;
+
+  done:
+    log->cons += len + 1;
+    return 0;
+
+  fail:
+    log->stats.fails++;
+    goto done;
+}
+
+static void tapdisk_syslog_ring_warning(td_syslog_t * log)
+{
+    int n, err;
+
+    n = log->oom;
+    log->oom = 0;
+
+    err = tapdisk_syslog(log, LOG_WARNING,
+                         "tapdisk-syslog: %d messages dropped", n);
+    if (err)
+        log->oom = n;
+}
+
+static void tapdisk_syslog_ring_dispatch(td_syslog_t * log)
+{
+    int err;
+
+    do {
+        err = tapdisk_syslog_ring_dispatch_one(log);
+    } while (!err);
+
+    if (log->oom)
+        tapdisk_syslog_ring_warning(log);
+}
+
+static int
+tapdisk_syslog_vsprintf(char *buf, size_t size,
+                        int prio, const struct timeval *tv,
+                        const char *ident, const char *fmt, va_list ap)
+{
+    char tsbuf[TD_SYSLOG_STRTIME_LEN + 1];
+    size_t len;
+
+    /*
+     * PKT       := PRI HEADER MSG
+     * PRI       := "<" {"0" .. "9"} ">"
+     * HEADER    := TIMESTAMP HOSTNAME
+     * MSG       := <TAG> <SEP> <CONTENT>
+     * SEP       := ":" | " " | "["
+     */
+
+    tapdisk_syslog_strftime(tsbuf, sizeof(tsbuf), tv);
+
+    len = 0;
+
+    /* NB. meant to work with c99 null buffers */
+
+    len += snprintf(buf ? buf + len : NULL, buf ? size - len : 0,
+                    "<%d>%s %s: ", prio, tsbuf, ident);
+
+    len += vsnprintf(buf ? buf + len : NULL, buf ? size - len : 0,
+                     fmt, ap);
+
+    return MIN(len, size);
+}
+
+/*
+ * NB. Sockets.
+ *
+ * Syslog is based on a connectionless (DGRAM) unix transport.
+ *
+ * While it is reliable, we cannot block on syslogd because -- as with
+ * any IPC in tapdisk -- we could deadlock in page I/O writeback.
+ * Hence the syslog(3) avoidance on the datapath, which this code
+ * facilitates.
+ *
+ * This type of socket has a single (global) receive buffer on
+ * syslogd's end, but no send buffer at all. The does just that:
+ * headroom on the sender side.
+ *
+ * The transport is rather stateless, but we still need to connect()
+ * the socket, or select() will find no receive buffer to block
+ * on. While we never disconnect, connections are unreliable because
+ * syslog may shut down.
+ *
+ * Reconnection will be attempted with every user message submitted.
+ * Any send() or connect() failure other than EAGAIN discards the
+ * message. Also, the write event handler will go on to discard any
+ * remaining ring contents as well, once the socket is disconnected.
+ *
+ * In summary, no attempts to mask service blackouts in here.
+ */
+
+int
+tapdisk_vsyslog(td_syslog_t * log, int prio, const char *fmt, va_list ap)
+{
+    struct timeval now;
+    size_t len;
+    int err;
+
+    gettimeofday(&now, NULL);
+
+    len = tapdisk_syslog_vsprintf(log->msg, TD_SYSLOG_PACKET_MAX,
+                                  prio | log->facility,
+                                  &now, log->ident, fmt, ap);
+
+    log->stats.count += 1;
+    log->stats.bytes += len;
+
+    if (log->cons != log->prod)
+        goto busy;
+
+  send:
+    err = tapdisk_syslog_sock_send(log, log->msg, len);
+    if (!err)
+        return 0;
+
+    if (err == -ENOTCONN) {
+        err = tapdisk_syslog_sock_connect(log);
+        if (!err)
+            goto send;
+    }
+
+    if (err != -EAGAIN)
+        goto fail;
+
+    tapdisk_syslog_sock_unmask(log);
+
+  busy:
+    if (log->oom) {
+        err = -ENOBUFS;
+        goto oom;
+    }
+
+    err = tapdisk_syslog_ring_write_str(log, log->msg, len);
+    if (!err)
+        return 0;
+
+    log->oom_tv = now;
+
+  oom:
+    log->oom++;
+    log->stats.drops++;
+    return err;
+
+  fail:
+    log->stats.fails++;
+    return err;
+}
+
+int tapdisk_syslog(td_syslog_t * log, int prio, const char *fmt, ...)
+{
+    va_list ap;
+    int err;
+
+    va_start(ap, fmt);
+    err = tapdisk_vsyslog(log, prio, fmt, ap);
+    va_end(ap);
+
+    return err;
+}
+
+static int
+tapdisk_syslog_sock_send(td_syslog_t * log, const void *msg, size_t size)
+{
+    ssize_t n;
+
+    log->stats.xmits++;
+
+    n = send(log->sock, msg, size, MSG_DONTWAIT);
+    if (n < 0)
+        return -errno;
+
+    return 0;
+}
+
+static void
+tapdisk_syslog_sock_event(event_id_t id __attribute__((unused)),
+        char mode __attribute__((unused)), void *private)
+{
+    td_syslog_t *log = private;
+
+    tapdisk_syslog_ring_dispatch(log);
+
+    if (log->cons == log->prod)
+        tapdisk_syslog_sock_mask(log);
+}
+
+static void __tapdisk_syslog_sock_init(td_syslog_t * log)
+{
+    log->sock = -1;
+    log->event_id = -1;
+}
+
+static void tapdisk_syslog_sock_close(td_syslog_t * log)
+{
+    if (log->sock >= 0)
+        close(log->sock);
+
+    if (log->event_id >= 0)
+        tapdisk_server_unregister_event(log->event_id);
+
+    __tapdisk_syslog_sock_init(log);
+}
+
+static int tapdisk_syslog_sock_open(td_syslog_t * log)
+{
+    event_id_t id;
+    int s, err;
+
+    __tapdisk_syslog_sock_init(log);
+
+    s = socket(PF_UNIX, SOCK_DGRAM, 0);
+    if (s < 0) {
+        err = -errno;
+        goto fail;
+    }
+
+    log->sock = s;
+
+#if 0
+    err = fcntl(s, F_SETFL, O_NONBLOCK);
+    if (err < 0) {
+        err = -errno;
+        goto fail;
+    }
+#endif
+
+    id = tapdisk_server_register_event(SCHEDULER_POLL_WRITE_FD,
+                                       s, 0,
+                                       tapdisk_syslog_sock_event, log);
+    if (id < 0) {
+        err = id;
+        goto fail;
+    }
+
+    log->event_id = id;
+
+    tapdisk_syslog_sock_mask(log);
+
+    return 0;
+
+  fail:
+    tapdisk_syslog_sock_close(log);
+    return err;
+}
+
+static int tapdisk_syslog_sock_connect(td_syslog_t * log)
+{
+    int err;
+
+    err = connect(log->sock, &syslog_addr, sizeof(syslog_addr));
+    if (err < 0)
+        err = -errno;
+
+    return err;
+}
+
+static void tapdisk_syslog_sock_mask(td_syslog_t * log)
+{
+    tapdisk_server_mask_event(log->event_id, 1);
+}
+
+static void tapdisk_syslog_sock_unmask(td_syslog_t * log)
+{
+    tapdisk_server_mask_event(log->event_id, 0);
+}
+
+void __tapdisk_syslog_init(td_syslog_t * log)
+{
+    memset(log, 0, sizeof(td_syslog_t));
+    __tapdisk_syslog_sock_init(log);
+    __tapdisk_syslog_ring_init(log);
+}
+
+void tapdisk_syslog_close(td_syslog_t * log)
+{
+    tapdisk_syslog_ring_uninit(log);
+    tapdisk_syslog_sock_close(log);
+
+    if (log->ident)
+        free(log->ident);
+
+    __tapdisk_syslog_init(log);
+}
+
+int
+tapdisk_syslog_open(td_syslog_t * log, const char *ident, int facility,
+                    size_t bufsz)
+{
+    int err;
+
+    __tapdisk_syslog_init(log);
+
+    log->facility = facility;
+    log->ident = ident ? strndup(ident, TD_SYSLOG_IDENT_MAX) : NULL;
+
+    err = tapdisk_syslog_sock_open(log);
+    if (err)
+        goto fail;
+
+    err = tapdisk_syslog_ring_init(log, bufsz);
+    if (err)
+        goto fail;
+
+    return 0;
+
+  fail:
+    tapdisk_syslog_close(log);
+
+    return err;
+}
+
+void tapdisk_syslog_stats(td_syslog_t * log, int prio)
+{
+    struct _td_syslog_stats *s = &log->stats;
+
+    tapdisk_syslog(log, prio,
+                   "tapdisk-syslog: %llu messages, %llu bytes, "
+                   "xmits: %llu, failed: %llu, dropped: %llu",
+                   s->count, s->bytes, s->xmits, s->fails, s->drops);
+}
+
+void tapdisk_syslog_flush(td_syslog_t * log)
+{
+    while (log->cons != log->prod)
+        tapdisk_server_iterate();
+}
diff --git a/tools/blktap3/drivers/tapdisk-syslog.h 
b/tools/blktap3/drivers/tapdisk-syslog.h
new file mode 100644
--- /dev/null
+++ b/tools/blktap3/drivers/tapdisk-syslog.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2009, XenSource Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of XenSource Inc. nor the names of its contributors
+ *       may be used to endorse or promote products derived from this software
+ *       without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __TAPDISK_SYSLOG_H__
+#define __TAPDISK_SYSLOG_H__
+
+#include <syslog.h>
+#include <stdarg.h>
+#include "scheduler.h"
+
+typedef struct _td_syslog td_syslog_t;
+
+#define TD_SYSLOG_PACKET_MAX  1024
+
+struct _td_syslog_stats {
+    unsigned long long count;
+    unsigned long long bytes;
+    unsigned long long xmits;
+    unsigned long long fails;
+    unsigned long long drops;
+};
+
+struct _td_syslog {
+    char *ident;
+    int facility;
+
+    int sock;
+    event_id_t event_id;
+
+    void *buf;
+    size_t bufsz;
+
+    char *msg;
+
+    char *ring;
+    size_t ringsz;
+
+    size_t prod;
+    size_t cons;
+
+    int oom;
+    struct timeval oom_tv;
+
+    struct _td_syslog_stats stats;
+};
+
+int tapdisk_syslog_open(td_syslog_t *,
+                        const char *ident, int facility, size_t bufsz);
+void tapdisk_syslog_close(td_syslog_t *);
+void tapdisk_syslog_flush(td_syslog_t *);
+void tapdisk_syslog_stats(td_syslog_t *, int prio);
+
+int tapdisk_vsyslog(td_syslog_t *, int prio, const char *fmt, va_list ap);
+int tapdisk_syslog(td_syslog_t *, int prio, const char *fmt, ...);
+
+#endif                          /* __TAPDISK_SYSLOG_H__ */

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.