>From Alan D. Brunelle <[EMAIL PROTECTED]>
Added per-IO block number dump (issued)
Signed-off-by: Alan D. Brunelle <[EMAIL PROTECTED]>
---
btt/Makefile | 2 +
btt/args.c | 12 +++++++-
btt/bno_dump.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++++
btt/bt_timeline.c | 3 +-
btt/devs.c | 1 +
btt/doc/btt.tex | 18 ++++++++++++
btt/globals.h | 10 +++++--
btt/trace_issue.c | 1 +
8 files changed, 121 insertions(+), 5 deletions(-)
diff --git a/btt/Makefile b/btt/Makefile
index c406ed3..17fb8c0 100644
--- a/btt/Makefile
+++ b/btt/Makefile
@@ -9,7 +9,7 @@ LIBS = $(PLIBS) $(ELIBS)
OBJS = args.o bt_timeline.o devmap.o devs.o dip_rb.o iostat.o latency.o \
misc.o output.o proc.o seek.o trace.o trace_complete.o trace_im.o \
trace_issue.o trace_queue.o trace_remap.o trace_requeue.o rbtree.o \
- mmap.o trace_plug.o
+ mmap.o trace_plug.o bno_dump.o
all: depend $(PROGS)
diff --git a/btt/args.c b/btt/args.c
index 7fa087e..4bbcf76 100644
--- a/btt/args.c
+++ b/btt/args.c
@@ -27,7 +27,7 @@
#include <fcntl.h>
#include "globals.h"
-#define S_OPTS "Ad:D:e:hi:I:l:M:o:p:q:s:S:t:T:Vv"
+#define S_OPTS "AB:d:D:e:hi:I:l:M:o:p:q:s:S:t:T:Vv"
static struct option l_opts[] = {
{
.name = "all-data",
@@ -36,6 +36,12 @@ static struct option l_opts[] = {
.val = 'A'
},
{
+ .name = "dump-blocknos",
+ .has_arg = required_argument,
+ .flag = NULL,
+ .val = 'B'
+ },
+ {
.name = "range-delta",
.has_arg = required_argument,
.flag = NULL,
@@ -144,6 +150,7 @@ static struct option l_opts[] = {
static char usage_str[] = \
"\n[ -A | --all-data ]\n" \
+ "[ -B <output name> | --dump-blocknos=<output name> ]\n" \
"[ -d <seconds> | --range-delta=<seconds> ]\n" \
"[ -D <dev;...> | --devices=<dev;...> ]\n" \
"[ -e <exe,...> | --exes=<exe,...> ]\n" \
@@ -177,6 +184,9 @@ void handle_args(int argc, char *argv[])
case 'A':
output_all_data = 1;
break;
+ case 'B':
+ bno_dump_name = strdup(optarg);
+ break;
case 'd':
sscanf(optarg, "%lf", &range_delta);
break;
diff --git a/btt/bno_dump.c b/btt/bno_dump.c
new file mode 100644
index 0000000..f0f16f6
--- /dev/null
+++ b/btt/bno_dump.c
@@ -0,0 +1,79 @@
+/*
+ * blktrace output analysis: generate a timeline & gather statistics
+ *
+ * Copyright (C) 2006 Alan D. Brunelle <[EMAIL PROTECTED]>
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+#include "globals.h"
+
+struct bno_dump {
+ FILE *rfp, *wfp, *cfp;
+};
+
+static struct file_info *bno_dump_files = NULL;
+
+static FILE *bno_dump_open(__u32 device, char rwc)
+{
+ FILE *fp;
+ char *oname;
+ int mjr, mnr;
+
+ mjr = device >> MINORBITS;
+ mnr = device & ((1 << MINORBITS) - 1);
+
+ oname = malloc(strlen(bno_dump_name) + 32);
+ sprintf(oname, "%s_%03d,%03d_%c.dat", bno_dump_name, mjr, mnr, rwc);
+ if ((fp = fopen(oname, "w")) == NULL)
+ perror(oname);
+ else
+ add_file(&bno_dump_files, fp, oname);
+ return fp;
+}
+
+void *bno_dump_init(__u32 device)
+{
+ struct bno_dump *bdp;
+
+ if (bno_dump_name == NULL) return NULL;
+
+ bdp = malloc(sizeof(*bdp));
+ bdp->rfp = bno_dump_open(device, 'r');
+ bdp->wfp = bno_dump_open(device, 'w');
+ bdp->cfp = bno_dump_open(device, 'c');
+
+ return bdp;
+}
+
+void bno_dump_add(void *handle, struct io *iop)
+{
+# define RW_FP(bdp, iop) (IOP_READ(iop) ? bdp->rfp : bdp->wfp)
+ struct bno_dump *bdp = handle;
+
+ if (bdp) {
+ if (RW_FP(bdp, iop))
+ fprintf(RW_FP(bdp, iop), "%15.9lf %lld\n",
+ BIT_TIME(iop->t.time), (long
long)BIT_START(iop));
+ if (bdp->cfp)
+ fprintf(bdp->cfp, "%15.9lf %lld\n",
+ BIT_TIME(iop->t.time), (long
long)BIT_START(iop));
+ }
+}
+
+void bno_dump_clean(void)
+{
+ clean_files(&bno_dump_files);
+}
diff --git a/btt/bt_timeline.c b/btt/bt_timeline.c
index c2a4abf..8ae046b 100644
--- a/btt/bt_timeline.c
+++ b/btt/bt_timeline.c
@@ -27,7 +27,7 @@
char bt_timeline_version[] = "0.99.1";
-char *devices, *exes, *input_name, *output_name, *seek_name;
+char *devices, *exes, *input_name, *output_name, *seek_name, *bno_dump_name;
char *d2c_name, *q2c_name, *per_io_name;
FILE *ranges_ofp, *avgs_ofp, *per_io_ofp;
int verbose, done, time_bounded, output_all_data;
@@ -100,6 +100,7 @@ int process(void)
seek_clean();
latency_clean();
+ bno_dump_clean();
gettimeofday(&tve, NULL);
if (verbose) {
diff --git a/btt/devs.c b/btt/devs.c
index a458a77..545d5c5 100644
--- a/btt/devs.c
+++ b/btt/devs.c
@@ -108,6 +108,7 @@ struct d_info *dip_add(__u32 device, struct io *iop)
dip->last_q = (__u64)-1;
dip->map = dev_map_find(device);
dip->seek_handle = seeki_init(device);
+ dip->bno_dump_handle = bno_dump_init(device);
latency_init(dip);
list_add_tail(&dip->hash_head, &dev_heads[DEV_HASH(device)]);
list_add_tail(&dip->all_head, &all_devs);
diff --git a/btt/doc/btt.tex b/btt/doc/btt.tex
index af585c5..88b772e 100644
--- a/btt/doc/btt.tex
+++ b/btt/doc/btt.tex
@@ -597,6 +597,7 @@ Device: rrqm/s wrqm/s r/s w/s rsec/s
wsec/s
\begin{verbatim}
Usage: \texttt{btt} 0.99.1
[ -A | --all-data ]
+[ -B <output name> | --dump-blocknos=<output name> ]
[ -d <seconds> | --range-delta=<seconds> ]
[ -D <dev;...> | --devices=<dev;...> ]
[ -e <exe,...> | --exes=<exe,...> ]
@@ -623,6 +624,23 @@ Usage: \texttt{btt} 0.99.1
section~\ref{sec:detailed-data}). If you desire that level of
detail you can specify this option.
+\subsection{\label{sec:o-B}\texttt{--dump-blocknos}/\texttt{-B}}
+
+ This option will output absolute block numbers to three files prefixed
+ by the specified output name:
+
+ \begin{description}
+ \item[\emph{prefix}\_\emph{device}\_r.dat] All read block numbers are
+ output, first column is time (seconds), second is the block number.
+
+ \item[\emph{prefix}\_\emph{device}\_w.dat] All write block numbers are
+ output, first column is time (seconds), second is the block number.
+
+ \item[\emph{prefix}\_\emph{device}\_c.dat] All block numbers (read
+ and write) are output, first column is time (seconds), second is
+ the block number.
+ \end{description}
+
\subsection{\label{sec:o-d}\texttt{--range-delta}/\texttt{-d}}
Section~\ref{sec:activity} discussed how \texttt{btt} outputs a file
diff --git a/btt/globals.h b/btt/globals.h
index b4e9894..e8b8e7e 100644
--- a/btt/globals.h
+++ b/btt/globals.h
@@ -159,7 +159,7 @@ struct d_info {
void *heads;
struct region_info regions;
struct devmap *map;
- void *seek_handle;
+ void *seek_handle, *bno_dump_handle;
FILE *d2c_ofp, *q2c_ofp;
struct avgs_info avgs;
struct stats stats, all_stats;
@@ -193,8 +193,9 @@ struct bilink {
extern char bt_timeline_version[], *devices, *exes, *input_name, *output_name;
extern char *seek_name, *iostat_name, *d2c_name, *q2c_name, *per_io_name;
+extern char *bno_dump_name;
extern double range_delta;
-extern FILE *ranges_ofp, *avgs_ofp, *iostat_ofp, *per_io_ofp;;
+extern FILE *ranges_ofp, *avgs_ofp, *iostat_ofp, *per_io_ofp;
extern int verbose, done, time_bounded, output_all_data;
extern unsigned int n_devs;
extern unsigned long n_traces;
@@ -279,6 +280,11 @@ struct p_info *find_process(__u32 pid, char *name);
void pip_update_q(struct io *iop);
void pip_foreach_out(void (*f)(struct p_info *, void *), void *arg);
+/* bno_dump.c */
+void *bno_dump_init(__u32 device);
+void bno_dump_add(void *handle, struct io *iop);
+void bno_dump_clean(void);
+
/* seek.c */
void *seeki_init(__u32 device);
void seek_clean(void);
diff --git a/btt/trace_issue.c b/btt/trace_issue.c
index 780a133..52aa8b1 100644
--- a/btt/trace_issue.c
+++ b/btt/trace_issue.c
@@ -91,6 +91,7 @@ void trace_issue(struct io *d_iop)
{
if (io_setup(d_iop, IOP_D)) {
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++;
if (!remapper_dev(d_iop->t.device))