]> xenbits.xensource.com Git - people/dstodden/blktap.git/commitdiff
CP-1840: More status info.
authorDaniel Stodden <daniel.stodden@citrix.com>
Tue, 31 Aug 2010 21:28:11 +0000 (14:28 -0700)
committerDaniel Stodden <daniel.stodden@citrix.com>
Tue, 31 Aug 2010 21:28:11 +0000 (14:28 -0700)
output:

 * vbd.secs: counts sectors served.
 * image.hits/fail: counts sectors completed/failed (not forwarded).
 * image.driver.name: shows driver names, not only numbers.

tapdisk-stats:

 * Move nesting depth tracking to __stats_push/__stats_pop.
 * Adds tapdisk_stats_val(...)/tapdisk_stats_vval(va), for arrays.

Signed-off-by: Daniel Stodden <daniel.stodden@citrix.com>
drivers/tapdisk-driver.c
drivers/tapdisk-image.c
drivers/tapdisk-image.h
drivers/tapdisk-stats.c
drivers/tapdisk-stats.h
drivers/tapdisk-vbd.c
drivers/tapdisk-vbd.h
drivers/tapdisk.h

index 00717bd6752f9701a92b40e6f07a83f7a0a89961..7a9cc604c7f7a36f35d01c6694d3e27be063ae88 100644 (file)
@@ -106,8 +106,13 @@ tapdisk_driver_debug(td_driver_t *driver)
 void
 tapdisk_driver_stats(td_driver_t *driver, td_stats_t *st)
 {
+       const disk_info_t *info;
+
        tapdisk_stats_field(st, "type", "d", driver->type);
 
+       info = tapdisk_disk_types[driver->type];
+       tapdisk_stats_field(st, "name", "s", info->name);
+
        if (driver->ops->td_stats) {
                tapdisk_stats_field(st, "status", "{");
                driver->ops->td_stats(driver, st);
index 19e308434a245c41db93a963bc8ffed518c83cec..bdeda4540bea75c8f107f573d46c4266fec95f73 100644 (file)
@@ -167,6 +167,16 @@ tapdisk_image_stats(td_image_t *image, td_stats_t *st)
        tapdisk_stats_enter(st, '{');
        tapdisk_stats_field(st, "name", "s", image->name);
 
+       tapdisk_stats_field(st, "hits", "[");
+       tapdisk_stats_val(st, "llu", image->stats.hits.rd);
+       tapdisk_stats_val(st, "llu", image->stats.hits.wr);
+       tapdisk_stats_leave(st, ']');
+
+       tapdisk_stats_field(st, "fail", "[");
+       tapdisk_stats_val(st, "llu", image->stats.fail.rd);
+       tapdisk_stats_val(st, "llu", image->stats.fail.wr);
+       tapdisk_stats_leave(st, ']');
+
        tapdisk_stats_field(st, "driver", "{");
        tapdisk_driver_stats(image->driver, st);
        tapdisk_stats_leave(st, '}');
index 508305c0a02c92cc6e53d6c513e8b674902e9dd2..7134be5bf19fa8acea06bbbcc36815364b8e289c 100644 (file)
@@ -44,6 +44,25 @@ struct td_image_handle {
        void                        *private;
 
        struct list_head             next;
+
+       /*
+        * Basic datapath statistics, in sectors read/written.
+        *
+        * hits:  requests completed by this image.
+        * fail:  requests completed with failure by this image.
+        *
+        * Not that we do not count e.g.
+        * miss:  requests forwarded.
+        * total: requests processed by this image.
+        *
+        * This is because we'd have to compensate for restarts due to
+        * -EBUSY conditions. Those can be extrapolated by following
+        * the chain instead: sum(image[i].hits, i=0..) == vbd.secs;
+        */
+       struct {
+               td_sector_count_t    hits;
+               td_sector_count_t    fail;
+       } stats;
 };
 
 td_image_t *tapdisk_image_allocate(char *, int, int, td_flag_t, void *);
index 40a80490231ed5e7ca1138fa61d020ef99dd40b8..c073fa2af27be94bc2dd609a616b4fe29937a464 100644 (file)
 #include <stdio.h>
 #include <stdarg.h>
 
+#include "tapdisk.h"
 #include "tapdisk-stats.h"
 
+#define BUG_ON(_cond) if (_cond) { td_panic(); }
+
 static void
-tapdisk_stats_vsprintf(td_stats_t *st,
+__stats_vsprintf(td_stats_t *st,
                      const char *fmt, va_list ap)
 {
-       st->pos += vsnprintf(st->pos, st->buf + st->size - st->pos, fmt, ap);
+       size_t size = st->buf + st->size - st->pos;
+       st->pos += vsnprintf(st->pos, size, fmt, ap);
 }
 
 static void __attribute__((format (printf, 2, 3)))
-tapdisk_stats_sprintf(td_stats_t *st,
+__stats_sprintf(td_stats_t *st,
                     const char *fmt, ...)
 {
        va_list ap;
 
        va_start(ap, fmt);
-       tapdisk_stats_vsprintf(st, fmt, ap);
+       __stats_vsprintf(st, fmt, ap);
        va_end(ap);
 }
 
-
-static inline void
-__tapdisk_stats_enter(td_stats_t *st, char t)
+static void
+__stats_enter(td_stats_t *st)
 {
-       tapdisk_stats_sprintf(st, "%c ", t);
-
        st->depth++;
+       BUG_ON(st->depth > TD_STATS_MAX_DEPTH);
        st->n_elem[st->depth] = 0;
 }
 
-void
-tapdisk_stats_enter(td_stats_t *st, char t)
+static void
+__stats_leave(td_stats_t *st)
+{
+       st->depth--;
+}
+
+static void
+__stats_next(td_stats_t *st)
 {
        int n_elem;
 
        n_elem = st->n_elem[st->depth];
        if (n_elem > 0)
-               tapdisk_stats_sprintf(st, ", ");
+               __stats_sprintf(st, ", ");
        st->n_elem[st->depth]++;
+}
 
-       __tapdisk_stats_enter(st, t);
+static void
+__tapdisk_stats_enter(td_stats_t *st, char t)
+{
+       __stats_sprintf(st, "%c ", t);
+       __stats_enter(st);
 }
 
+void
+tapdisk_stats_enter(td_stats_t *st, char t)
+{
+       __stats_next(st);
+       __tapdisk_stats_enter(st, t);
+}
 
 void
 tapdisk_stats_leave(td_stats_t *st, char t)
 {
-       st->depth--;
+       __stats_leave(st);
+       __stats_sprintf(st, " %c", t);
+}
 
-       tapdisk_stats_sprintf(st, " %c", t);
+static void
+tapdisk_stats_vval(td_stats_t *st, const char *conv, va_list ap)
+{
+       char t = conv[0], fmt[32];
+
+       __stats_next(st);
+
+       switch (t) {
+       case 's':
+               __stats_vsprintf(st, "\"%s\"", ap);
+               break;
+
+       default:
+               sprintf(fmt, "%%%s", conv);
+               __stats_vsprintf(st, fmt, ap);
+               break;
+       }
+}
+
+void
+tapdisk_stats_val(td_stats_t *st, const char *conv, ...)
+{
+       va_list ap;
+
+       va_start(ap, conv);
+       tapdisk_stats_vval(st, conv, ap);
+       va_end(ap);
 }
 
 void
@@ -87,38 +134,30 @@ tapdisk_stats_field(td_stats_t *st, const char *key, const char *conv, ...)
 {
        va_list ap;
        int n_elem;
-       char fmt[32], t;
+       char t;
 
        n_elem = st->n_elem[st->depth]++;
        if (n_elem > 0)
-               tapdisk_stats_sprintf(st, ", ");
+               __stats_sprintf(st, ", ");
 
-       tapdisk_stats_sprintf(st, "\"%s\": ", key);
+       __stats_sprintf(st, "\"%s\": ", key);
 
        if (!conv) {
-               tapdisk_stats_sprintf(st, "null");
+               __stats_sprintf(st, "null");
                return;
        }
 
        t = conv[0];
        switch (t) {
-       case 's':
-               va_start(ap, conv);
-               tapdisk_stats_vsprintf(st, "\"%s\"", ap);
-               va_end(ap);
-               break;
-
        case '[':
        case '{':
                __tapdisk_stats_enter(st, t);
                break;
-
        default:
-               sprintf(fmt, "%%%s", conv);
-
                va_start(ap, conv);
-               tapdisk_stats_vsprintf(st, fmt, ap);
+               __stats_enter(st);
+               tapdisk_stats_vval(st, conv, ap);
+               __stats_leave(st);
                va_end(ap);
-               break;
        }
 }
index cf41aa76568c8a334142036f87fdf3af441d0e57..5110fa2433aa0485c8ae62fbcbca4603fb02f016 100644 (file)
@@ -32,7 +32,7 @@
 
 #include <string.h>
 
-#define TD_INFO_MAX_DEPTH 8
+#define TD_STATS_MAX_DEPTH 8
 
 struct tapdisk_stats_ctx {
        void           *pos;
@@ -40,7 +40,7 @@ struct tapdisk_stats_ctx {
        void           *buf;
        size_t          size;
 
-       int             n_elem[TD_INFO_MAX_DEPTH];
+       int             n_elem[TD_STATS_MAX_DEPTH];
        int             depth;
 };
 
@@ -65,5 +65,6 @@ tapdisk_stats_length(td_stats_t *st)
 void tapdisk_stats_enter(td_stats_t *st, char t);
 void tapdisk_stats_leave(td_stats_t *st, char t);
 void tapdisk_stats_field(td_stats_t *st, const char *key, const char *conv, ...);
+void tapdisk_stats_val(td_stats_t *st, const char *conv, ...);
 
 #endif /* _TAPDISK_STATS_H_ */
index e20fbde8e356c06843815561bd43437a83e2c890..77aa4f11b29262452283aca05272086b95673587 100644 (file)
@@ -1645,12 +1645,21 @@ static void
 __tapdisk_vbd_complete_td_request(td_vbd_t *vbd, td_vbd_request_t *vreq,
                                  td_request_t treq, int res)
 {
+       td_image_t *image = treq.image, *prev, *tmp;
        int err;
 
        err = (res <= 0 ? res : -res);
        vbd->secs_pending  -= treq.secs;
        vreq->secs_pending -= treq.secs;
 
+       if (err != -EBUSY) {
+               int write = treq.op == TD_OP_WRITE;
+               td_sector_count_add(&image->stats.hits, treq.secs, write);
+               if (err)
+                       td_sector_count_add(&image->stats.fail,
+                                           treq.secs, write);
+       }
+
        if (err) {
                vreq->status = BLKIF_RSP_ERROR;
                vreq->error  = (vreq->error ? : err);
@@ -1953,6 +1962,21 @@ tapdisk_vbd_reissue_failed_requests(td_vbd_t *vbd)
        return err;
 }
 
+static void
+tapdisk_vbd_count_new_request(td_vbd_t *vbd, td_vbd_request_t *vreq)
+{
+       blkif_request_t *req = &vreq->req;
+       struct blkif_request_segment *seg;
+       int write;
+
+       write = req->operation == BLKIF_OP_WRITE;
+
+       for (seg = &req->seg[0]; seg < &req->seg[req->nr_segments]; seg++) {
+               int secs = seg->last_sect - seg->first_sect + 1;
+               td_sector_count_add(&vbd->secs, secs, write);
+       }
+}
+
 static int
 tapdisk_vbd_issue_new_requests(td_vbd_t *vbd)
 {
@@ -1963,6 +1987,8 @@ tapdisk_vbd_issue_new_requests(td_vbd_t *vbd)
                err = tapdisk_vbd_issue_request(vbd, vreq);
                if (err)
                        return err;
+
+               tapdisk_vbd_count_new_request(vbd, vreq);
        }
 
        return 0;
@@ -2190,11 +2216,14 @@ tapdisk_vbd_stats(td_vbd_t *vbd, td_stats_t *st)
        tapdisk_stats_field(st, "name", "s", vbd->name);
        tapdisk_stats_field(st, "minor", "d", vbd->minor);
 
-       tapdisk_stats_field(st, "image", "[");
+       tapdisk_stats_field(st, "secs", "[");
+       tapdisk_stats_val(st, "llu", vbd->secs.rd);
+       tapdisk_stats_val(st, "llu", vbd->secs.wr);
+       tapdisk_stats_leave(st, ']');
 
+       tapdisk_stats_field(st, "images", "[");
        tapdisk_vbd_for_each_image(vbd, image, next)
                tapdisk_image_stats(image, st);
-
        tapdisk_stats_leave(st, ']');
 
        tapdisk_stats_leave(st, '}');
index 935b2414ce0656f860a326b216551c4412e16a7d..dc7b908e5700bd3b91acccf8d83920ab61443653 100644 (file)
@@ -137,6 +137,7 @@ struct td_vbd_handle {
        uint64_t                    secs_pending;
        uint64_t                    retries;
        uint64_t                    errors;
+       td_sector_count_t           secs;
 
        uint64_t                    kicks_in;
        uint64_t                    kicks_out;
index 494b7dcb7faf9ab0b8e4a00ee301e2c44591c9d2..58aa661eee732ba4c78b87c0f9998025a64e3267 100644 (file)
@@ -108,6 +108,7 @@ typedef struct td_disk_info          td_disk_info_t;
 typedef struct td_request            td_request_t;
 typedef struct td_driver_handle      td_driver_t;
 typedef struct td_image_handle       td_image_t;
+typedef struct td_sector_count       td_sector_count_t;
 
 /* 
  * Prototype of the callback to activate as requests complete.
@@ -159,6 +160,20 @@ struct tap_disk {
        void (*td_stats)             (td_driver_t *, td_stats_t *);
 };
 
+struct td_sector_count {
+       td_sector_t rd;
+       td_sector_t wr;
+};
+
+static inline void
+td_sector_count_add(td_sector_count_t *s, td_sector_t v, int write)
+{
+       if (write)
+               s->wr += v;
+       else
+               s->rd += v;
+}
+
 void td_panic(void);
 
 #endif