]> xenbits.xensource.com Git - people/dstodden/blktap.git/commitdiff
CA-27472: Log past events to a ring buffer
authorDaniel Stodden <daniel.stodden@citrix.com>
Wed, 8 Jul 2009 02:39:30 +0000 (19:39 -0700)
committerDaniel Stodden <daniel.stodden@citrix.com>
Wed, 8 Jul 2009 02:39:30 +0000 (19:39 -0700)
Adds debug code to the main event loop to trace unexpectedly high
event frequencies we sometimes seem to come across.

Comprises a 1K ring buffer and makes the select loop append fd sets
plus relative time into it. We cover up to 128 events. We only cover
the lower 32 fds to save space, but that's usually more than needed.

drivers/Makefile
drivers/scheduler.c
drivers/scheduler.h
drivers/tapdisk-event-log.c [new file with mode: 0644]
drivers/tapdisk-event-log.h [new file with mode: 0644]
drivers/tapdisk-server.c
drivers/tapdisk-server.h

index a404c85877ad551cb185ca93d23985c5aa2edf79..1804b8a5820bf6e7c6b77e4b4e65b21226c5d80c 100644 (file)
@@ -44,6 +44,7 @@ TAP-OBJS  += tapdisk-server.o
 TAP-OBJS  += tapdisk-queue.o
 TAP-OBJS  += tapdisk-filter.o
 TAP-OBJS  += tapdisk-log.o
+TAP-OBJS  += tapdisk-event-log.o
 TAP-OBJS  += tapdisk-utils.o
 TAP-OBJS  += io-optimize.o
 TAP-OBJS  += lock.o
index 6b8d0093e7a8cc243903aeddccabc8c0c304dfbf..40c80e15b4b8df4ea6a510d39d987107c72930b8 100644 (file)
@@ -238,6 +238,9 @@ scheduler_wait_for_events(scheduler_t *s)
        ret = select(s->max_fd + 1, &s->read_fds,
                     &s->write_fds, &s->except_fds, &tv);
 
+       td_event_log_add_events(&s->event_log, ret,
+                               &s->read_fds, &s->write_fds, &s->except_fds);
+
        s->restart     = 0;
        s->timeout     = SCHEDULER_MAX_TIMEOUT;
        s->max_timeout = SCHEDULER_MAX_TIMEOUT;
@@ -262,4 +265,6 @@ scheduler_initialize(scheduler_t *s)
        FD_ZERO(&s->except_fds);
 
        INIT_LIST_HEAD(&s->events);
+
+       td_event_log_init(&s->event_log);
 }
index ea37e8f837f36e918e9355dfc0c53705ca318454..ecb5da5646aea4d99f1cc69df65270c3e433974a 100644 (file)
@@ -31,6 +31,7 @@
 #include <sys/select.h>
 
 #include "list.h"
+#include "tapdisk-event-log.h"
 
 #define SCHEDULER_POLL_READ_FD       0x1
 #define SCHEDULER_POLL_WRITE_FD      0x2
@@ -52,6 +53,8 @@ typedef struct scheduler {
        int                          timeout;
        int                          restart;
        int                          max_timeout;
+
+       struct event_log             event_log;
 } scheduler_t;
 
 void scheduler_initialize(scheduler_t *);
diff --git a/drivers/tapdisk-event-log.c b/drivers/tapdisk-event-log.c
new file mode 100644 (file)
index 0000000..f6942e5
--- /dev/null
@@ -0,0 +1,133 @@
+/* 
+ * 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 <stdio.h>
+#include <string.h>
+#include <time.h>
+#include <sys/time.h>
+
+#include "tapdisk-event-log.h"
+#include "tapdisk-log.h"
+
+#ifndef MIN
+#define MIN(a, b) ((a) <= (b) ? (a) : (b))
+#endif
+
+void
+td_event_log_init(struct event_log *log)
+{
+       memset(log, 0, sizeof(struct event_log));
+}
+
+static struct event_log_entry*
+td_event_log_add(struct event_log *log)
+{
+       struct event_log_entry *entry;
+
+       entry = __td_event_log_entry(log->count, log);
+
+       gettimeofday(&entry->ts, NULL);
+       entry->fds = 0;
+
+       log->count++;
+
+       return entry;
+}
+
+
+void
+td_event_log_add_events(struct event_log *log, int nfds,
+                       const fd_set *rdfds, const fd_set *wrfds,
+                       const fd_set *exfds)
+{
+       struct event_log_entry *entry;
+       int i;
+
+       if (nfds < 0)
+               return;
+
+       entry = td_event_log_add(log);
+
+       if (!nfds)
+               return;
+
+       for (i = 0; i < sizeof(entry->fds) * 8; ++i) {
+               int count =
+                       (rdfds ? FD_ISSET(i, rdfds) : 0) +
+                       (wrfds ? FD_ISSET(i, wrfds) : 0) +
+                       (exfds ? FD_ISSET(i, exfds) : 0);
+               if (!count)
+                       continue;
+
+               entry->fds |= (1<<i);
+
+               nfds -= count;
+               if (!nfds)
+                       break;
+       }
+
+       if (nfds)
+               entry->fds |= TD_EVENT_LOG_OTHER;
+}
+
+void
+td_event_log_write(struct event_log *log, int level)
+{
+       int i, j, N;
+       struct event_log_entry *prev;
+
+       N = td_event_log_num_entries(log);
+
+       prev = NULL;
+
+       for (i = 0; i < N; i += j) {
+               char buf[256], *pos = buf;
+
+               for (j = 0; j < 8 && i+j < N; ++j) {
+                       struct event_log_entry *entry;
+                       struct timeval delta;
+
+                       delta.tv_sec = delta.tv_usec = 0;
+
+                       entry = td_event_log_entry(i+j, log);
+
+                       if (prev)
+                               timersub(&entry->ts, &prev->ts, &delta);
+
+                       pos += snprintf(pos, buf + sizeof(buf) - pos,
+                                       " %ld.%06ld:%lx",
+                                       delta.tv_sec, delta.tv_usec,
+                                       entry->fds);
+
+                       prev = entry;
+               }
+
+               tlog_write(level, "[%lld/%lld]:%s\n",
+                          log->count - N + i, log->count, buf);
+       }
+}
diff --git a/drivers/tapdisk-event-log.h b/drivers/tapdisk-event-log.h
new file mode 100644 (file)
index 0000000..e7f820a
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2008, 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 _EVENT_LOG_H_
+#define _EVENT_LOG_H_
+
+#include <sys/select.h>
+
+#define TD_EVENT_LOG_N_ENTRIES 128
+
+struct event_log_entry {
+       struct timeval          ts;
+       long                    fds;
+};
+
+struct event_log {
+       struct event_log_entry  ring[TD_EVENT_LOG_N_ENTRIES];
+       unsigned long long      count;
+};
+
+/* NB. Reuse low fds <= 2, these are dupd to /dev/null */
+#define TD_EVENT_LOG_OTHER      (1<<0)
+
+#define td_event_log_num_entries(_s)                   \
+       MIN((_s)->count, TD_EVENT_LOG_N_ENTRIES)
+
+#define td_event_log_first(_s)                         \
+       ((_s)->count < TD_EVENT_LOG_N_ENTRIES           \
+        ? 0                                            \
+        : (_s)->count % TD_EVENT_LOG_N_ENTRIES)
+
+#define __td_event_log_entry(_i, _s)                   \
+       &(_s)->ring[(_i) % TD_EVENT_LOG_N_ENTRIES]
+
+#define td_event_log_entry(_n, _s)                     \
+       __td_event_log_entry(td_event_log_first(_s) + (_n), _s)
+
+void td_event_log_init(struct event_log *log);
+
+void td_event_log_add_events(struct event_log *log, int nfds,
+                            const fd_set *rdfds, const fd_set *wrfds,
+                            const fd_set *exfds);
+
+void td_event_log_write(struct event_log *log, int level);
+
+#endif /* _EVENT_LOG_H_ */
index 60aa0b301fb583f85ad65ebb5f811935467bfa1c..a01e28f8d1ffe257f9e560b1284fee9b9940375c 100644 (file)
@@ -425,3 +425,20 @@ tapdisk_server_run()
 
        return 0;
 }
+
+void
+tapdisk_server_log_events(void)
+{
+       td_vbd_t *vbd, *next;
+       int i;
+
+       tlog_write(TLOG_WARN, "index: ipc rfd:%x wfd:%x aio:%x other:%x\n",
+                  1<<server.ipc.rfd, 1<<server.ipc.wfd, 1<<server.aio_queue.poll_fd,
+                  1<<TD_EVENT_LOG_OTHER);
+
+       i = 0;
+       tapdisk_server_for_each_vbd(vbd, next)
+               tlog_write(TLOG_WARN, "index: vbd [%d]:%x\n", i++, 1<<vbd->ring.fd);
+
+       td_event_log_write(&server.scheduler.event_log, TLOG_WARN);
+}
index a051d94be8f1d03fe6686fcb5e0f5e799f96a4a7..bc170bf371e654ea3b03347f8ce12a097af2a50f 100644 (file)
@@ -49,5 +49,6 @@ void tapdisk_server_set_max_timeout(int);
 
 int tapdisk_server_initialize(const char *, const char *);
 int tapdisk_server_run(void);
+void tapdisk_server_log_events(void);
 
 #endif