From: "Alan D. Brunelle" <Alan.Brunelle@hp.com>
To: linux-btrace@vger.kernel.org
Subject: Re: Negative queue lengths in btt "iostat" output?
Date: Fri, 30 May 2008 15:30:55 +0000 [thread overview]
Message-ID: <48401DAF.6000802@hp.com> (raw)
In-Reply-To: <483CA8B7.2090008@cesmail.net>
[-- Attachment #1: Type: text/plain, Size: 652 bytes --]
M. Edward (Ed) Borasky wrote:
> I'm experimenting with "btt" and I have a case where the "iostat"
> emulation is generating negative queue lengths. They seem to be steadily
> increasing in magnitude. The utilizations don't look right, either -- I
> don't think this device was 100 percent busy for the entire run.
>
> I've attached a sample -- the input files are huge, but I'll post them
> if you need them.
>
>
Hi Ed -
If you get a chance, could you try the attached patch - I have not
committed it, although it looks solid enough. I'm going to keep plugging
on this. [Note the stuff about await & svctm in the patch description.]
Thanks,
Alan
[-- Attachment #2: 0001-Massive-re-write-of-iostat-capability.patch --]
[-- Type: text/x-diff, Size: 22965 bytes --]
From c66b8b2a18b467e5f3205f7187c37f5d7d58fc52 Mon Sep 17 00:00:00 2001
From: Alan D. Brunelle <alan.brunelle@hp.com>
Date: Fri, 30 May 2008 11:25:11 -0400
Subject: [PATCH] Massive re-write of iostat capability
rrqm/s, wrqm/s, r/s, w/s, rkB/s, wkB/s, avgrq-sz, avgqu-sz, and %util
all look good -- match up well w/ iostat. await & svctm do /not/ match
up well w/ iostat, but "look" right when looking at the raw data.
For the record:
await == Average time between GETRQ and COMPLETION for all I/O requests
completed in that sample.
svctm == Averate time between ISSUE and COMPLETION for all I/O requests
completed in that sample
Signed-off-by: Alan D. Brunelle <alan.brunelle@hp.com>
---
btt/bt_timeline.c | 6 +-
btt/devs.c | 3 +
btt/globals.h | 50 +++---
btt/iostat.c | 467 ++++++++++++++++++++++++++++----------------------
btt/trace_complete.c | 16 ++-
btt/trace_im.c | 5 +-
btt/trace_issue.c | 2 +-
7 files changed, 310 insertions(+), 239 deletions(-)
diff --git a/btt/bt_timeline.c b/btt/bt_timeline.c
index 2eed087..8c5739e 100644
--- a/btt/bt_timeline.c
+++ b/btt/bt_timeline.c
@@ -60,14 +60,10 @@ int main(int argc, char *argv[])
handle_args(argc, argv);
init_dev_heads();
- iostat_init();
if (process() || output_avgs(avgs_ofp) || output_ranges(ranges_ofp))
return 1;
- if (iostat_ofp) {
- fprintf(iostat_ofp, "\n");
- iostat_dump_stats(iostat_last_stamp, 1);
- }
+ iostat_dump_stats();
if (msgs_ofp != stdout)
fclose(msgs_ofp);
diff --git a/btt/devs.c b/btt/devs.c
index 3cf7a6c..4e2ca4c 100644
--- a/btt/devs.c
+++ b/btt/devs.c
@@ -89,6 +89,7 @@ void dip_exit(void)
unplug_hist_exit(dip->unplug_hist_handle);
if (output_all_data)
q2d_release(dip->q2d_priv);
+ iostat_free(dip->stats);
free(dip);
}
}
@@ -127,6 +128,8 @@ struct d_info *dip_add(__u32 device, struct io *iop)
dip->pre_culling = 1;
if (output_all_data)
dip->q2d_priv = q2d_init();
+ make_dev_hdr(str, 256, dip, 1);
+ dip->stats = iostat_alloc(str);
n_devs++;
}
diff --git a/btt/globals.h b/btt/globals.h
index c4b7674..fc358b6 100644
--- a/btt/globals.h
+++ b/btt/globals.h
@@ -41,7 +41,7 @@
#define BIT_START(iop) ((iop)->t.sector)
#define BIT_END(iop) ((iop)->t.sector + ((iop)->t.bytes >> 9))
#define IOP_READ(iop) ((iop)->t.action & BLK_TC_ACT(BLK_TC_READ))
-#define IOP_RW(iop) (IOP_READ(iop) ? 1 : 0)
+#define IOP_RW(iop) (IOP_READ(iop) ? 0 : 1)
#define TO_SEC(nanosec) ((double)(nanosec) / 1.0e9)
#define TO_MSEC(nanosec) (1000.0 * TO_SEC(nanosec))
@@ -128,18 +128,6 @@ struct devmap {
char device[32], node[32], pci[32], devno[32];
};
-struct stats {
- __u64 rqm[2], ios[2], sec[2], wait, svctm;
- double last_qu_change, last_dev_change, tot_qusz, idle_time;
- int cur_qusz, cur_dev;
-};
-
-struct stats_t {
- double n;
- double rqm_s[2], ios_s[2], sec_s[2];
- double avgrq_sz, avgqu_sz, await, svctm, p_util;
-};
-
struct d_info {
struct list_head all_head, hash_head;
void *heads;
@@ -149,7 +137,7 @@ struct d_info {
void *q2d_priv;
FILE *d2c_ofp, *q2c_ofp;
struct avgs_info avgs;
- struct stats stats, all_stats;
+ void *stats;
__u64 last_q, n_qs, n_ds;
__u64 n_act_q, t_act_q; /* # currently active when Q comes in */
__u32 device;
@@ -193,7 +181,7 @@ extern struct avgs_info all_avgs;
extern __u64 last_q;
extern struct region_info all_regions;
extern struct list_head all_ios, free_ios;
-extern __u64 iostat_interval, iostat_last_stamp;
+extern __u64 iostat_interval;
extern time_t genesis, last_vtrace;
extern double t_astart, t_aend;
extern __u64 q_histo[N_HIST_BKTS], d_histo[N_HIST_BKTS];
@@ -221,6 +209,10 @@ void dip_plug(__u32 dev, double cur_time);
void dip_unplug(__u32 dev, double cur_time, __u64 nio_ups);
void dip_unplug_tm(__u32 dev, __u64 nio_ups);
void dip_exit(void);
+static inline void *dip_get_stats(struct d_info *dip)
+{
+ return dip->stats;
+}
/* dip_rb.c */
int rb_insert(struct rb_root *root, struct io *iop);
@@ -230,14 +222,26 @@ void rb_foreach(struct rb_node *n, struct io *iop,
struct list_head *head);
/* iostat.c */
-void iostat_init(void);
-void iostat_getrq(struct io *iop);
-void iostat_merge(struct io *iop);
-void iostat_issue(struct io *iop);
-void iostat_unissue(struct io *iop);
-void iostat_complete(struct io *d_iop, struct io *c_iop);
-void iostat_check_time(__u64 stamp);
-void iostat_dump_stats(__u64 stamp, int all);
+void *iostat_alloc(char *hdr);
+void iostat_free(void *dsp);
+void iostat_insert(void *arg, struct io *i_iop);
+void iostat_issue(void *arg, struct io *d_iop);
+void iostat_merge(void *arg, struct io *iop);
+void iostat_complete(void *arg, struct io *c_iop, __u64 d2c, __u64 g2c,
+ unsigned int nqs);
+void __iostat_check_time(__u64 now);
+void __iostat_dump_stats(void);
+
+static inline void iostat_check_time(__u64 now)
+{
+ if (iostat_ofp)
+ __iostat_check_time(now);
+}
+static inline void iostat_dump_stats(void)
+{
+ if (iostat_ofp)
+ __iostat_dump_stats();
+}
/* latency.c */
void latency_init(struct d_info *dip);
diff --git a/btt/iostat.c b/btt/iostat.c
index d701e2f..88373be 100644
--- a/btt/iostat.c
+++ b/btt/iostat.c
@@ -1,7 +1,7 @@
/*
* blktrace output analysis: generate a timeline & gather statistics
*
- * Copyright (C) 2006 Alan D. Brunelle <Alan.Brunelle@hp.com>
+ * Copyright (C) 2006-2008 Alan D. Brunelle <Alan.Brunelle@hp.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -18,194 +18,244 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
-#include <stdio.h>
-#include <unistd.h>
+
+#include <float.h>
#include "globals.h"
-#define INC_STAT(dip, fld) \
- do { \
- (dip)->stats. fld ++; \
- (dip)->all_stats. fld ++; \
- } while (0)
-
-#define DEC_STAT(dip, fld) \
- do { \
- (dip)->stats. fld --; \
- (dip)->all_stats. fld --; \
- } while (0)
-
-#define ADD_STAT(dip, fld, val) \
- do { \
- __u64 __v = (val); \
- (dip)->stats. fld += __v; \
- (dip)->all_stats. fld += __v; \
- } while (0)
-
-#define SUB_STAT(dip, fld, val) \
- do { \
- __u64 __v = (val); \
- (dip)->stats. fld -= __v; \
- (dip)->all_stats. fld -= __v; \
- } while (0)
-
-__u64 last_start, iostat_last_stamp;
+struct __stats {
+ __u64 sectors[2], ios[2], merges[2]; // READ & WRITE
+};
+
+struct disk_stats {
+ struct list_head head;
+ char *hdr;
+ __u64 stamp;
+ __u64 last_q, last_idle, busy_ticks;
+ __u64 rq_ticks, nqs, io_ticks;
+ long long in_flight, qusz;
+ double avgqsz;
+ struct __stats stats[2]; /* 0 == last values */
+
+ double sum_merges[2], sum_ios[2], sum_secs[2];
+ double sum_avgqsz, sum_await, sum_svctm, sum_util;
+};
+
+static __u64 last_seen = (__u64)-1;
+static __u64 last_start = (__u64)-1;
+static int ndumps = 0;
+
__u64 iostat_interval = 1000000000;
char *iostat_name = NULL;
FILE *iostat_ofp = NULL;
-void dump_hdr(void)
+#define delta_fld(dsp, fld) ((dsp)->stats[1]. fld - (dsp)->stats[0]. fld)
+
+static void clear_stats(struct __stats *sp)
{
- fprintf(iostat_ofp, "Device: rrqm/s wrqm/s r/s w/s "
- "rsec/s wsec/s rkB/s wkB/s "
- "avgrq-sz avgqu-sz await svctm %%util Stamp\n");
+ memset(sp, 0, sizeof(*sp));
}
-void iostat_init(void)
+void *iostat_alloc(char *hdr)
{
- last_start = (__u64)-1;
- if (iostat_ofp)
- dump_hdr();
+ struct disk_stats *dsp = malloc(sizeof(*dsp));
+
+ memset(dsp, 0, sizeof(*dsp));
+ dsp->hdr = strdup(hdr);
+
+ return dsp;
}
-void update_tot_qusz(struct d_info *dip, double now)
+void iostat_free(void *arg)
{
- dip->stats.tot_qusz += ((now - dip->stats.last_qu_change) *
- dip->stats.cur_qusz);
- dip->all_stats.tot_qusz += ((now - dip->all_stats.last_qu_change) *
- dip->all_stats.cur_qusz);
+ struct disk_stats *dsp = arg;
- dip->stats.last_qu_change = dip->all_stats.last_qu_change = now;
+ free(dsp->hdr);
+ free(dsp);
}
-void update_idle_time(struct d_info *dip, double now, int force)
+void iostat_insert(void *arg, struct io *i_iop)
{
- if (dip->stats.cur_dev == 0 || force) {
- dip->stats.idle_time += (now - dip->stats.last_dev_change);
- dip->all_stats.idle_time +=
- (now - dip->all_stats.last_dev_change);
+ struct disk_stats *dsp = arg;
+
+ if (dsp->qusz > 0) {
+ double dt = TO_SEC(i_iop->t.time - dsp->last_q);
+ dsp->avgqsz += ((double)(dsp->qusz) * dt);
}
- dip->stats.last_dev_change = dip->all_stats.last_dev_change = now;
+
+ dsp->qusz++;
+ dsp->last_q = i_iop->t.time;
}
-void __dump_stats(__u64 stamp, int all, struct d_info *dip, struct stats_t *asp)
+void iostat_issue(void *arg, struct io *d_iop)
{
- char hdr[16];
- struct stats *sp;
- double dt, nios, avgrq_sz, p_util, nrqm, await, svctm;
- double now = TO_SEC(stamp);
-
- if (all) {
- dt = (double)stamp / 1.0e9;
- sp = &dip->all_stats;
- }
- else {
- dt = (double)(stamp-last_start) / 1.0e9;
- sp = &dip->stats;
- }
+ struct disk_stats *dsp = arg;
+
+ if (dsp->in_flight == 0)
+ dsp->last_idle = d_iop->t.time;
+
+ dsp->in_flight++;
+}
+
+void iostat_merge(void *arg, struct io *iop)
+{
+ struct disk_stats *dsp = arg;
+ dsp->stats[1].merges[IOP_RW(iop)]++;
+}
+
+void iostat_complete(void *arg, struct io *c_iop, __u64 d2c, __u64 g2c,
+ unsigned int nqs)
+{
+ struct disk_stats *dsp = arg;
+ int rw = IOP_RW(c_iop);
+
+ dsp->stats[1].sectors[rw] += (c_iop->t.bytes >> 9);
+ dsp->stats[1].ios[rw]++;
- nios = (double)(sp->ios[0] + sp->ios[1]);
- nrqm = (double)(sp->rqm[0] + sp->rqm[1]);
- update_idle_time(dip, now, 1);
- update_tot_qusz(dip, now);
+ dsp->nqs += nqs;
+ if (g2c != (__u64)-1)
+ dsp->rq_ticks += g2c;
+ if (d2c != (__u64)-1)
+ dsp->io_ticks += d2c;
- if (nios > 0.0) {
- avgrq_sz = (double)(sp->sec[0] + sp->sec[1]) / nios;
- svctm = TO_MSEC(sp->svctm) / nios;
+ if (dsp->in_flight == 1)
+ dsp->busy_ticks += (c_iop->t.time - dsp->last_idle);
+ dsp->in_flight--;
+
+ if (dsp->qusz > 0) {
+ double dt = TO_SEC(c_iop->t.time - dsp->last_q);
+ dsp->avgqsz += ((double)(dsp->qusz) * dt);
}
- else
- avgrq_sz = svctm = 0.0;
- await = ((nios + nrqm) > 0.0) ? TO_MSEC(sp->wait) / (nios+nrqm) : 0.0;
- p_util = (sp->idle_time <= dt) ? 100.0 * (1.0 - (sp->idle_time / dt)) :
- 0.0;
+ dsp->qusz--;
+ dsp->last_q = c_iop->t.time;
+}
- /*
- * For AWAIT: nios should be the same as number of inserts
- * and we add in nrqm (number of merges), which should give
- * us the total number of IOs sent to the block IO layer.
- */
- fprintf(iostat_ofp, "%-11s ", make_dev_hdr(hdr, 11, dip, 1));
- fprintf(iostat_ofp, "%8.2lf ", (double)sp->rqm[1] / dt);
- fprintf(iostat_ofp, "%8.2lf ", (double)sp->rqm[0] / dt);
- fprintf(iostat_ofp, "%7.2lf ", (double)sp->ios[1] / dt);
- fprintf(iostat_ofp, "%7.2lf ", (double)sp->ios[0] / dt);
- fprintf(iostat_ofp, "%9.2lf ", (double)sp->sec[1] / dt);
- fprintf(iostat_ofp, "%9.2lf ", (double)sp->sec[0] / dt);
- fprintf(iostat_ofp, "%9.2lf ", (double)(sp->sec[1] / 2) / dt);
- fprintf(iostat_ofp, "%9.2lf ", (double)(sp->sec[0] / 2) / dt);
- fprintf(iostat_ofp, "%8.2lf ", avgrq_sz);
- fprintf(iostat_ofp, "%8.2lf ", (double)sp->tot_qusz / dt);
- fprintf(iostat_ofp, "%7.2lf ", await);
- fprintf(iostat_ofp, "%7.2lf ", svctm);
- fprintf(iostat_ofp, "%6.2lf", p_util);
- if (all)
- fprintf(iostat_ofp, "%8s\n", "TOTAL");
- else {
- fprintf(iostat_ofp, "%8.2lf\n", TO_SEC(stamp));
- sp->rqm[0] = sp->rqm[1] = 0;
- sp->ios[0] = sp->ios[1] = 0;
- sp->sec[0] = sp->sec[1] = 0;
- sp->wait = sp->svctm = 0;
+void sum_results(struct disk_stats *dsp, double *merges, double *ios,
+ double *secs, double avgqsz, double await,
+ double svctm, double util)
+{
+ int i;
- sp->tot_qusz = sp->idle_time = 0.0;
+ for (i = 0; i < 2; i++) {
+ dsp->sum_merges[i] += merges[i];
+ dsp->sum_ios[i] += ios[i];
+ dsp->sum_secs[i] += secs[i];
}
- if (asp) {
- int i;
+ dsp->sum_avgqsz += avgqsz;
+ dsp->sum_await += await;
+ dsp->sum_svctm += svctm;
+ dsp->sum_util += util;
+}
- asp->n += 1.0;
- for (i = 0; i < 2; i++) {
- asp->rqm_s[i] += ((double)sp->rqm[i] / dt);
- asp->ios_s[i] += ((double)sp->ios[i] / dt);
- asp->sec_s[i] += ((double)sp->sec[i] / dt);
- }
- asp->avgrq_sz += avgrq_sz;
- asp->avgqu_sz += (double)sp->tot_qusz / dt;
- asp->await += await;
- asp->svctm += svctm;
- asp->p_util += p_util;
+void dump_hdr(FILE *ofp)
+{
+ fprintf(ofp,
+ "%13s %8s %8s %8s %8s %8s %8s %8s %8s %8s %8s %6s %s\n",
+ "Device", "rrqm/s", "wrqm/s", "r/s", "w/s",
+ "rkB/s", "wkB/s", "avgrq-sz", "avgqu-sz", "await",
+ "svctm", "%util", "Stamp");
+}
+
+void dump(struct disk_stats *dsp, struct disk_stats *adsp, __u64 now,
+ double dt, char *tail)
+{
+ FILE *ofp = iostat_ofp;
+ double await, arqsz, busy_ticks, util, svctm;
+ double merges[2] = {
+ (double)delta_fld(dsp, merges[0]),
+ (double)delta_fld(dsp, merges[1])
+ };
+ double secs[2] = {
+ (double)delta_fld(dsp, sectors[0]),
+ (double)delta_fld(dsp, sectors[1])
+ };
+ double ios[2] = {
+ (double)delta_fld(dsp, ios[0]),
+ (double)delta_fld(dsp, ios[1])
+ };
+ double nios = ios[0] + ios[1];
+ double avgqsz = dsp->avgqsz / dt;
+
+ busy_ticks = TO_SEC(dsp->busy_ticks);
+ util = 100.0 * (busy_ticks / dt);
+
+ if (ios[0] || ios[1]) {
+ arqsz = (secs[0] + secs[1]) / nios;
+ await = 1000.0 * (TO_SEC(dsp->rq_ticks) / dsp->nqs);
+ svctm = 1000.0 * (TO_SEC(dsp->io_ticks) / nios);
}
+ else
+ await = arqsz = svctm = 0.0;
+
+ fprintf(ofp, "%13s ", dsp->hdr);
+ fprintf(ofp, "%8.2f %8.2f ", merges[0] / dt, merges[1] / dt);
+ fprintf(ofp, "%8.2f %8.2f ", ios[0] / dt, ios[1] / dt);
+ fprintf(ofp, "%8.1f %8.1f ", secs[0] / (2 * dt), secs[1] / (2 * dt));
+ fprintf(ofp, "%8.2f ", arqsz);
+ fprintf(ofp, "%8.2f ", avgqsz);
+ fprintf(ofp, "%8.2f ", await);
+ fprintf(ofp, "%8.2f ", svctm);
+ fprintf(ofp, "%6.2f ", util);
+ fprintf(ofp, "%6s\n", tail);
+
+ /*
+ * Accumulate results
+ */
+ sum_results(dsp, merges, ios, secs, avgqsz, await, svctm, util);
+ sum_results(adsp, merges, ios, secs, avgqsz, await, svctm, util);
+
+ /*
+ * Clear out counters, save current stats as previous.
+ */
+ dsp->busy_ticks = 0;
+ dsp->last_idle = now;
+ dsp->rq_ticks = dsp->io_ticks = 0;
+ dsp->nqs = 0;
+ dsp->last_q = now;
+ dsp->avgqsz = 0.0;
+
+ memcpy(&dsp->stats[0], &dsp->stats[1], sizeof(dsp->stats[1]));
}
-void __dump_stats_t(__u64 stamp, struct stats_t *asp, int all)
+void dump_a(struct disk_stats *dsp, double dt, int ndevs, int ndumps,
+ char *pre, char *pst)
{
- if (asp->n < 2.0) return; // What's the point?
-
- fprintf(iostat_ofp, "%-11s ", "TOTAL");
- fprintf(iostat_ofp, "%8.2lf ", asp->rqm_s[0]);
- fprintf(iostat_ofp, "%8.2lf ", asp->rqm_s[1]);
- fprintf(iostat_ofp, "%7.2lf ", asp->ios_s[0]);
- fprintf(iostat_ofp, "%7.2lf ", asp->ios_s[1]);
- fprintf(iostat_ofp, "%9.2lf ", asp->sec_s[0]);
- fprintf(iostat_ofp, "%9.2lf ", asp->sec_s[1]);
- fprintf(iostat_ofp, "%9.2lf ", asp->sec_s[0] / 2.0);
- fprintf(iostat_ofp, "%9.2lf ", asp->sec_s[1] / 2.0);
- fprintf(iostat_ofp, "%8.2lf ", asp->avgrq_sz / asp->n);
- fprintf(iostat_ofp, "%8.2lf ", asp->avgqu_sz / asp->n);
- fprintf(iostat_ofp, "%7.2lf ", asp->await / asp->n);
- fprintf(iostat_ofp, "%7.2lf ", asp->svctm / asp->n);
- fprintf(iostat_ofp, "%6.2lf", asp->p_util / asp->n);
- if (all)
- fprintf(iostat_ofp, "%8s\n", "TOTAL");
- else
- fprintf(iostat_ofp, "%8.2lf\n", TO_SEC(stamp));
+ FILE *ofp = iostat_ofp;
+ double rd_merges = dsp->sum_merges[0];
+ double wr_merges = dsp->sum_merges[1];
+ double rd_ios = dsp->sum_ios[0];
+ double wr_ios = dsp->sum_ios[1];
+ double nios = rd_ios + wr_ios;
+ double rd_sec = dsp->sum_secs[0];
+ double wr_sec = dsp->sum_secs[1];
+ double arqsz = (rd_ios || wr_ios) ? (rd_sec + wr_sec) / nios : 0.0;
+
+ fprintf(ofp, "%13s ", pre);
+ fprintf(ofp, "%8.2f %8.2f ", rd_merges / dt, wr_merges / dt);
+ fprintf(ofp, "%8.2f %8.2f ", rd_ios / dt, wr_ios / dt);
+ fprintf(ofp, "%8.1f %8.1f ", rd_sec / (2 * dt), wr_sec / (2 * dt));
+ fprintf(ofp, "%8.2f ", arqsz);
+ fprintf(ofp, "%8.2f ", dsp->sum_avgqsz / (double)(ndevs * ndumps));
+ fprintf(ofp, "%8.2f ", dsp->sum_await / (double)(ndevs * ndumps));
+ fprintf(ofp, "%8.2f ", dsp->sum_svctm / (double)(ndevs * ndumps));
+ fprintf(ofp, "%6.2f ", dsp->sum_util / (double)(ndevs * ndumps));
+ fprintf(ofp, "%6s\n", pst);
}
-void iostat_dump_stats(__u64 stamp, int all)
+void collect_dsps(struct list_head *head)
{
struct d_info *dip;
- struct stats_t as;
-
- memset(&as, 0, sizeof(struct stats_t));
- if (all)
- dump_hdr();
+ struct disk_stats *dsp;
if (devices == NULL) {
struct list_head *p;
__list_for_each(p, &all_devs) {
dip = list_entry(p, struct d_info, all_head);
- __dump_stats(stamp, all, dip, &as);
+ dsp = dip_get_stats(dip);
+
+ list_add_tail(&dsp->head, head);
}
}
else {
@@ -215,82 +265,91 @@ void iostat_dump_stats(__u64 stamp, int all)
while (p && ((i = sscanf(p, "%u,%u", &mjr, &mnr)) == 2)) {
dip = __dip_find((__u32)((mjr << MINORBITS) | mnr));
- __dump_stats(stamp, all, dip, &as);
+ dsp = dip_get_stats(dip);
+
+ list_add_tail(&dsp->head, head);
p = strchr(p, ';');
if (p) p++;
}
}
-
- __dump_stats_t(stamp, &as, all);
-
- if (!all && iostat_ofp)
- fprintf(iostat_ofp, "\n");
}
-void iostat_check_time(__u64 stamp)
+void dump_stats(__u64 now, int clear0)
{
- if (iostat_ofp) {
- if (last_start == (__u64)-1)
- last_start = stamp;
- else if ((stamp - last_start) >= iostat_interval) {
- iostat_dump_stats(stamp, 0);
- last_start = stamp;
- }
-
- iostat_last_stamp = stamp;
+ double dt = TO_SEC(now - last_start);
+ int ndevs = 0;
+ char buf[128];
+ struct disk_stats adsp, *dsp;
+ struct list_head *p, *q;
+ LIST_HEAD(dsps);
+
+ memset(&adsp, 0, sizeof(adsp));
+ adsp.hdr = "TOTAL";
+
+ sprintf(buf, "%6.1lf", TO_SEC(now));
+ collect_dsps(&dsps);
+
+ list_for_each_safe(p, q, &dsps) {
+ dsp = list_entry(p, struct disk_stats, head);
+ list_del(&dsp->head);
+
+ if (dsp->in_flight)
+ dsp->busy_ticks += (now - dsp->last_idle);
+ if (clear0)
+ clear_stats(&dsp->stats[0]);
+ dump(dsp, &adsp, now, dt, buf);
+ ndevs++;
}
-}
-
-void iostat_getrq(struct io *iop)
-{
- update_tot_qusz(iop->dip, TO_SEC(iop->t.time));
- INC_STAT(iop->dip, cur_qusz);
-}
-
-void iostat_merge(struct io *iop)
-{
- INC_STAT(iop->dip, rqm[IOP_RW(iop)]);
-}
-
-void iostat_issue(struct io *iop)
-{
- int rw = IOP_RW(iop);
- struct d_info *dip = iop->dip;
- double now = TO_SEC(iop->t.time);
- INC_STAT(dip, ios[rw]);
- ADD_STAT(dip, sec[rw], iop->t.bytes >> 9);
+ if (ndevs > 1) {
+ dump_a(&adsp, dt, ndevs, 1, "ITER", "AVG");
+ fprintf(iostat_ofp, "\n");
+ }
- update_idle_time(dip, now, 0);
- INC_STAT(dip, cur_dev);
+ ndumps++;
}
-void iostat_unissue(struct io *iop)
+void __iostat_check_time(__u64 now)
{
- int rw = IOP_RW(iop);
- struct d_info *dip = iop->dip;
+ if (!iostat_ofp)
+ return;
+ if (last_start == (__u64)-1) {
+ dump_hdr(iostat_ofp);
+ last_start = now;
+ }
+ else if ((now - last_start) >= iostat_interval) {
+ dump_stats(now, 0);
+ last_start = now;
+ }
- DEC_STAT(dip, ios[rw]);
- SUB_STAT(dip, sec[rw], iop->t.bytes >> 9);
- DEC_STAT(dip, cur_dev);
+ last_seen = now;
}
-void iostat_complete(struct io *q_iop, struct io *c_iop)
+void __iostat_dump_stats(void)
{
- double now = TO_SEC(c_iop->t.time);
- struct d_info *dip = q_iop->dip;
-
- if (q_iop->i_time != (__u64)-1)
- ADD_STAT(c_iop->dip, wait, tdelta(q_iop->i_time,c_iop->t.time));
- else if (q_iop->m_time != (__u64)-1)
- ADD_STAT(c_iop->dip, wait, tdelta(q_iop->m_time,c_iop->t.time));
-
- update_tot_qusz(dip, now);
- DEC_STAT(dip, cur_qusz);
-
- update_idle_time(dip, now, 0);
- DEC_STAT(dip, cur_dev);
+ int ndevs = 0;
+ LIST_HEAD(dsps);
+ struct list_head *p, *q;
+ struct disk_stats adsp, *dsp;
+
+ dump_stats(last_seen, 0);
+ fprintf(iostat_ofp, "\n");
+
+ memset(&adsp, 0, sizeof(adsp));
+ adsp.hdr = "TOTAL";
+
+ collect_dsps(&dsps);
+ list_for_each_safe(p, q, &dsps) {
+ dsp = list_entry(p, struct disk_stats, head);
+ list_del(&dsp->head);
+ ndevs++;
+
+ sum_results(&adsp, dsp->sum_merges, dsp->sum_ios,
+ dsp->sum_secs, dsp->sum_avgqsz,
+ dsp->sum_await, dsp->sum_svctm, dsp->sum_util);
+ }
- ADD_STAT(dip, svctm, tdelta(q_iop->t.time, c_iop->t.time));
+ dump_hdr(iostat_ofp);
+ dump_a(&adsp, TO_SEC(last_seen), ndevs, ndumps, "TOTAL", "AVG");
}
diff --git a/btt/trace_complete.c b/btt/trace_complete.c
index 41bcb7d..2afda15 100644
--- a/btt/trace_complete.c
+++ b/btt/trace_complete.c
@@ -51,8 +51,11 @@ static void display_io_track(FILE *ofp, struct io *iop)
static void handle_complete(struct io *c_iop)
{
+ unsigned int nqs = 0;
LIST_HEAD(head);
struct list_head *p, *q;
+ __u64 g2c = (__u64)-1;
+ __u64 d2c = (__u64)-1;
update_blks(c_iop);
update_cregion(&all_regions, c_iop->t.time);
@@ -71,11 +74,10 @@ static void handle_complete(struct io *c_iop)
latency_q2c(q_iop->dip, q_iop->t.time, q2c);
if (q_iop->d_time != (__u64)-1) {
- __u64 d2c = tdelta(q_iop->d_time, c_iop->t.time);
-
+ if (d2c == (__u64)-1)
+ d2c = tdelta(q_iop->d_time, c_iop->t.time);
update_d2c(q_iop, d2c);
latency_d2c(q_iop->dip, c_iop->t.time, d2c);
- iostat_complete(q_iop, c_iop);
}
if (per_io_ofp) {
@@ -85,9 +87,17 @@ static void handle_complete(struct io *c_iop)
display_io_track(per_io_ofp, q_iop);
}
+ if (q_iop->g_time != (__u64)-1) {
+ if (g2c == (__u64)-1)
+ g2c = tdelta(q_iop->g_time, c_iop->t.time);
+ nqs++;
+ }
+
list_del(&q_iop->f_head);
io_release(q_iop);
}
+
+ iostat_complete(dip_get_stats(c_iop->dip), c_iop, d2c, g2c, nqs);
}
void trace_complete(struct io *c_iop)
diff --git a/btt/trace_im.c b/btt/trace_im.c
index 49c876c..0cb6690 100644
--- a/btt/trace_im.c
+++ b/btt/trace_im.c
@@ -24,8 +24,6 @@ static void handle_g(struct io *g_iop)
{
struct io *q_iop;
- iostat_getrq(g_iop);
-
q_iop = dip_find_sec(g_iop->dip, IOP_Q, g_iop->t.sector);
if (q_iop) {
q_iop->g_time = g_iop->t.time;
@@ -52,13 +50,14 @@ static void handle_i(struct io *i_iop)
if (q_iop->g_time != (__u64)-1)
update_g2i(q_iop, tdelta(q_iop->g_time, i_iop->t.time));
}
+ iostat_insert(dip_get_stats(i_iop->dip), i_iop);
}
static void handle_m(struct io *m_iop)
{
struct io *q_iop;
- iostat_merge(m_iop);
+ iostat_merge(dip_get_stats(m_iop->dip), m_iop);
q_iop = dip_find_sec(m_iop->dip, IOP_Q, m_iop->t.sector);
if (q_iop) {
diff --git a/btt/trace_issue.c b/btt/trace_issue.c
index a18d44d..1a4a203 100644
--- a/btt/trace_issue.c
+++ b/btt/trace_issue.c
@@ -30,8 +30,8 @@ static void handle_issue(struct io *d_iop)
seeki_add(d_iop->dip->seek_handle, d_iop);
bno_dump_add(d_iop->dip->bno_dump_handle, d_iop);
- iostat_issue(d_iop);
d_iop->dip->n_ds++;
+ iostat_issue(dip_get_stats(d_iop->dip), d_iop);
if (!remapper_dev(d_iop->t.device))
update_d_histo(d_iop->t.bytes);
--
1.5.4.3
prev parent reply other threads:[~2008-05-30 15:30 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-05-28 0:35 Negative queue lengths in btt "iostat" output? M. Edward (Ed) Borasky
2008-05-28 11:03 ` Alan D. Brunelle
2008-05-30 15:30 ` Alan D. Brunelle [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=48401DAF.6000802@hp.com \
--to=alan.brunelle@hp.com \
--cc=linux-btrace@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.