|
[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
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |