Commit a9e4ac1f authored by Bas Zoetekouw's avatar Bas Zoetekouw Committed by Dmitry Smirnov

Imported Debian snapshot 0.99.3+git-20080213182518-1

parent 5649866e
......@@ -5,7 +5,8 @@ PROGS = blkparse blktrace verify_blkparse blkrawverify
LIBS = -lpthread
SCRIPTS = btrace
ALL = $(PROGS) $(SCRIPTS) btt/btt btreplay/btrecord btreplay/btreplay
ALL = $(PROGS) $(SCRIPTS) btt/btt btreplay/btrecord btreplay/btreplay \
btt/bno_plot.py
all: $(ALL)
......
......@@ -8,9 +8,8 @@
CC = gcc
CFLAGS = -Wall -W -O2 -g
INCS = -I. -I..
OCFLAGS = -UCOUNT_IOS -UDEBUG -DNDEBUG
XCFLAGS = -D_GNU_SOURCE -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64
override CFLAGS += $(INCS) $(XCFLAGS) $(OCFLAGS)
override CFLAGS += $(INCS) $(XCFLAGS)
PROGS = btt
LIBS = $(PLIBS) $(ELIBS)
......
......@@ -205,7 +205,6 @@ static FILE *setup_ofile(char *fname)
}
buf = malloc(SETBUFFER_SIZE);
assert(buf);
setbuffer(ofp, buf, SETBUFFER_SIZE);
add_file(&arg_files, ofp, fname);
......
......@@ -69,7 +69,7 @@ void bno_dump_exit(void *param)
static inline void bno_dump_write(FILE *fp, struct io *iop)
{
fprintf(fp, "%15.9lf %lld %lld\n",
BIT_TIME(iop->t.time),
BIT_TIME(iop->t.time),
(long long)BIT_START(iop), (long long)BIT_END(iop));
}
......
#! /usr/bin/env python
#
# btt blkno plotting interface
#
# (C) Copyright 2008 Hewlett-Packard Development Company, L.P.
#
# 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
#
"""
bno_plot.py
[ -h | --help ]
[ -K | --keys-below ]
[ -v | --verbose ]
[ <file...> ]
Utilizes gnuplot to generate a 3D plot of the block number output
from btt. If no <files> are specified, it will utilize all files
generated after btt was run with -B blknos (meaning: all files of the
form blknos*[rw].dat).
The -K option forces bno_plot.py to put the keys below the graph,
typically all keys for input files are put in the upper right corner
of the graph. If the number of devices exceed 10, then bno_plot.py will
automatically push the keys under the graph.
To exit the plotter, enter 'quit' or ^D at the 'gnuplot> ' prompt.
"""
import getopt, glob, os, sys, tempfile
verbose = 0
cmds = """
set title 'btt Generated Block Accesses'
set xlabel 'Time (secs)'
set ylabel 'Block Number'
set zlabel '# Blocks per IO'
set grid
"""
#-----------------------------------------------------------------------------
def parse_args(in_args):
global verbose
keys_below = False
s_opts = 'hKv'
l_opts = [ 'help', 'keys-below', 'verbose' ]
try:
(opts, args) = getopt.getopt(in_args, s_opts, l_opts)
except getopt.error, msg:
print >>sys.stderr, msg
print >>sys.stderr, __doc__
sys.exit(1)
for (o, a) in opts:
if o in ('-h', '--help'):
print __doc__
sys.exit(0)
elif o in ('-v', '--verbose'):
verbose += 1
elif o in ('-K', '--keys-below'):
keys_below = True
if len(args) > 0: bnos = args
else: bnos = glob.glob('blknos*[rw].dat')
return (bnos, keys_below)
#-----------------------------------------------------------------------------
if __name__ == '__main__':
(bnos, keys_below) = parse_args(sys.argv[1:])
if verbose:
print 'Using files:',
for bno in bnos: print bno,
if keys_below: print '\nKeys are to be placed below graph'
else: print ''
tmpdir = tempfile.mktemp()
os.mkdir(tmpdir)
plot_cmd = None
for f in bnos:
t = '%s/%s' % (tmpdir, f)
fo = open(t, 'w')
for line in open(f, 'r'):
fld = line.split(None)
print >>fo, fld[0], fld[1], int(fld[2])-int(fld[1])
fo.close()
t = t[t.rfind('/')+1:]
if plot_cmd == None: plot_cmd = "splot '%s'" % t
else: plot_cmd = "%s,'%s'" % (plot_cmd, t)
fo = open('%s/plot.cmds' % tmpdir, 'w')
print >>fo, cmds
if len(bnos) > 10 or keys_below: print >>fo, 'set key below'
print >>fo, plot_cmd
fo.close()
pid = os.fork()
if pid == 0:
cmd = '/usr/bin/gnuplot %s/plot.cmds -' % tmpdir
if verbose: print 'Executing %s' % cmd
cmd = cmd.split(None)
os.chdir(tmpdir)
os.execvp(cmd[0], cmd)
sys.exit(1)
os.waitpid(pid, 0)
os.system('/bin/rm -rf ' + tmpdir)
......@@ -25,7 +25,7 @@
#include <time.h>
#include "globals.h"
char bt_timeline_version[] = "2.00";
char bt_timeline_version[] = "2.02";
char *devices, *exes, *input_name, *output_name, *seek_name, *bno_dump_name;
char *d2c_name, *q2c_name, *per_io_name, *unplug_hist_name;
......@@ -38,6 +38,7 @@ unsigned int n_devs;
time_t genesis, last_vtrace;
LIST_HEAD(all_devs);
LIST_HEAD(all_procs);
LIST_HEAD(all_ios);
LIST_HEAD(free_ios);
LIST_HEAD(free_bilinks);
__u64 q_histo[N_HIST_BKTS], d_histo[N_HIST_BKTS];
......@@ -50,15 +51,6 @@ struct region_info all_regions = {
.cranges = LIST_HEAD_INIT(all_regions.cranges),
};
#if defined(DEBUG)
int rb_tree_size;
#endif
#if defined(COUNT_IOS)
unsigned long nios_reused, nios_alloced, nios_freed;
LIST_HEAD(cios);
#endif
int process(void);
int main(int argc, char *argv[])
......@@ -75,9 +67,9 @@ int main(int argc, char *argv[])
iostat_dump_stats(iostat_last_stamp, 1);
}
if (ranges_ofp != stdout)
if (ranges_ofp != stdout)
fclose(ranges_ofp);
if (avgs_ofp != stdout)
if (avgs_ofp != stdout)
fclose(avgs_ofp);
seek_clean();
......@@ -92,6 +84,7 @@ int main(int argc, char *argv[])
free(input_name);
if (output_name) free(output_name);
clean_args();
clean_bufs();
return 0;
......@@ -120,40 +113,13 @@ int process(void)
if (verbose) {
double tps, dt_input = tv2dbl(&tve) - tv2dbl(&tvs);
tps = (double)n_traces / dt_input;
printf("\r "
" \r");
printf("%10lu traces @ %.1lf Ktps in %.6lf seconds\n",
n_traces, tps/1000.0,
dt_input);
# if defined(DEBUG)
printf("\ttree = |%d|\n", rb_tree_size);
if (rb_tree_size > 0)
dump_rb_trees();
# endif
# if defined(COUNT_IOS)
{
struct io *_iop;
struct list_head *_p;
FILE *_ofp = fopen("cios.txt", "w");
printf("(%ld + %ld) = %ld - %ld = %ld\n",
nios_alloced, nios_reused,
nios_alloced + nios_reused,
nios_freed,
(nios_alloced + nios_reused)
- nios_freed);
__list_for_each(_p, &cios) {
_iop = list_entry(_p, struct io,
cio_head);
__dump_iop(_ofp, _iop, 0);
}
fclose(_ofp);
}
# endif
}
return ret;
......
......@@ -52,50 +52,6 @@ static void __destroy_heads(struct rb_root *roots)
free(roots);
}
#if defined(DEBUG)
void __dump_rb_node(struct rb_node *n)
{
struct io *iop = rb_entry(n, struct io, rb_node);
dbg_ping();
__dump_iop(stdout, iop, 0);
if (n->rb_left)
__dump_rb_node(n->rb_left);
if (n->rb_right)
__dump_rb_node(n->rb_right);
}
void __dump_rb_tree(struct d_info *dip, enum iop_type type)
{
struct rb_root *roots = dip->heads;
struct rb_root *root = &roots[type];
struct rb_node *n = root->rb_node;
if (n) {
printf("\tIOP_%c\n", type2c(type));
__dump_rb_node(n);
}
}
void dump_rb_trees(void)
{
int i;
enum iop_type type;
struct d_info *dip;
struct list_head *p;
for (i = 0; i < N_DEV_HASH; i++) {
__list_for_each(p, &dev_heads[i]) {
dip = list_entry(p, struct d_info, hash_head);
printf("Trees for %3d,%-3d\n", MAJOR(dip->device),
MINOR(dip->device));
for (type = IOP_Q; type < N_IOP_TYPES; type++)
__dump_rb_tree(dip, type);
}
}
}
#endif
void init_dev_heads(void)
{
int i;
......@@ -184,11 +140,6 @@ struct d_info *dip_add(__u32 device, struct io *iop)
iop->linked = dip_rb_ins(dip, iop);
dip->end_time = BIT_TIME(iop->t.time);
# if defined(DEBUG)
if (iop->linked)
rb_tree_size++;
# endif
return dip;
}
......@@ -200,7 +151,7 @@ void dip_rem(struct io *iop)
}
}
void dip_foreach(struct io *iop, enum iop_type type,
void dip_foreach(struct io *iop, enum iop_type type,
void (*fnc)(struct io *iop, struct io *this), int rm_after)
{
if (rm_after) {
......@@ -211,7 +162,7 @@ void dip_foreach(struct io *iop, enum iop_type type,
dip_rb_fe(iop->dip, type, iop, fnc, &head);
list_for_each_safe(p, q, &head) {
this = list_entry(p, struct io, f_head);
LIST_DEL(&this->f_head);
list_del(&this->f_head);
io_release(this);
}
}
......@@ -244,10 +195,7 @@ void dip_foreach_out(void (*func)(struct d_info *, void *), void *arg)
while (p && ((i = sscanf(p, "%u,%u", &mjr, &mnr)) == 2)) {
dip = __dip_find((__u32)((mjr << MINORBITS) | mnr));
ASSERT(dip);
func(dip, arg);
p = strchr(p, ';');
if (p) p++;
}
......@@ -264,15 +212,25 @@ void dip_plug(__u32 dev, double cur_time)
dip->last_plug = cur_time;
}
void dip_unplug(__u32 dev, double cur_time, int is_timer)
void dip_unplug(__u32 dev, double cur_time, __u64 nios_up)
{
struct d_info *dip = __dip_find(dev);
if (!dip || !dip->is_plugged) return;
if (dip && dip->is_plugged) {
dip->nplugs++;
dip->plugged_time += (cur_time - dip->last_plug);
dip->is_plugged = 0;
dip->nios_up += nios_up;
}
}
dip->nplugs++;
if (is_timer) dip->n_timer_unplugs++;
void dip_unplug_tm(__u32 dev, __u64 nios_up)
{
struct d_info *dip = __dip_find(dev);
dip->plugged_time += (cur_time - dip->last_plug);
dip->is_plugged = 0;
if (dip && dip->is_plugged) {
dip->n_timer_unplugs++;
dip->nios_upt += nios_up;
dip->nplugs_t++;
}
}
......@@ -28,7 +28,6 @@ int rb_insert(struct rb_root *root, struct io *iop)
struct rb_node **p = &root->rb_node;
__u64 __s, s = BIT_START(iop);
ASSERT(root != NULL && iop != NULL);
while (*p) {
parent = *p;
__iop = rb_entry(parent, struct io, rb_node);
......@@ -65,7 +64,7 @@ struct io *rb_find_sec(struct rb_root *root, __u64 sec)
return NULL;
}
void rb_foreach(struct rb_node *n, struct io *iop,
void rb_foreach(struct rb_node *n, struct io *iop,
void (*fnc)(struct io *iop, struct io *this),
struct list_head *head)
{
......@@ -76,10 +75,8 @@ void rb_foreach(struct rb_node *n, struct io *iop,
if ((iop_s <= this_s) && (this_e <= iop_e)) {
if (fnc) fnc(iop, this);
if (head) {
ASSERT(this->f_head.next == LIST_POISON1);
if (head)
list_add_tail(&this->f_head, head);
}
}
if (iop_s < this_s)
rb_foreach(n->rb_left, iop, fnc, head);
......
DOCTMP = btt.log btt.aux btt.dvi btt.toc
DOCTMP = btt.log btt.aux btt.dvi btt.toc btt.tex.bak
all: btt.pdf
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -18,7 +18,6 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
......@@ -47,27 +46,6 @@
#define TO_SEC(nanosec) ((double)(nanosec) / 1.0e9)
#define TO_MSEC(nanosec) (1000.0 * TO_SEC(nanosec))
#if defined(DEBUG)
#define DBG_PING() dbg_ping()
#define ASSERT(truth) do { \
if (!(truth)) { \
DBG_PING(); \
assert(truth); \
} \
} while (0)
#define LIST_DEL(hp) list_del(hp)
#else
#define ASSERT(truth)
#define DBG_PING()
#define LIST_DEL(hp) do { \
ASSERT((hp)->next != NULL); \
ASSERT(!list_empty(hp)); \
list_del(hp); \
} while (0)
#endif
enum iop_type {
IOP_Q = 0,
IOP_X = 1,
......@@ -106,12 +84,19 @@ struct avg_info {
};
struct avgs_info {
struct avg_info q2q_dm;
struct avg_info q2a_dm;
struct avg_info q2c_dm;
struct avg_info q2q;
struct avg_info q2c;
struct avg_info q2a; /* Q to (A or X) */
struct avg_info q2i; /* Q to (I or M) */
struct avg_info i2d; /* (I or M) to D */
struct avg_info q2a;
struct avg_info q2g;
struct avg_info g2i;
struct avg_info q2m;
struct avg_info i2d;
struct avg_info m2d;
struct avg_info d2c;
struct avg_info q2c;
struct avg_info blks; /* Blocks transferred */
};
......@@ -168,27 +153,24 @@ struct d_info {
__u32 device;
int pre_culling;
int is_plugged, nplugs, n_timer_unplugs;
int is_plugged, nplugs, nplugs_t, n_timer_unplugs;
__u64 nios_up, nios_upt;
double start_time, last_plug, plugged_time, end_time;
};
struct io {
struct rb_node rb_node;
struct list_head f_head;
struct list_head f_head, a_head;
struct d_info *dip;
struct p_info *pip;
void *pdu;
__u64 bytes_left, i_time, gm_time, d_time, c_time, d_sec, c_sec;
__u64 bytes_left, g_time, i_time, m_time, d_time, c_time, d_sec, c_sec;
__u32 d_nsec, c_nsec;
struct blk_io_trace t;
int linked, is_getrq;
int linked;
enum iop_type type;
#if defined(COUNT_IOS)
struct list_head cio_head;
#endif
};
/* bt_timeline.c */
......@@ -205,21 +187,15 @@ extern struct list_head all_devs, all_procs;
extern struct avgs_info all_avgs;
extern __u64 last_q;
extern struct region_info all_regions;
extern struct list_head free_ios;
extern struct list_head all_ios, free_ios;
extern __u64 iostat_interval, iostat_last_stamp;
extern time_t genesis, last_vtrace;
extern double t_astart, t_aend;
extern __u64 q_histo[N_HIST_BKTS], d_histo[N_HIST_BKTS];
#if defined(DEBUG)
extern int rb_tree_size;
#endif
#if defined(COUNT_IOS)
extern unsigned long nios_reused, nios_alloced, nios_freed;
extern struct list_head cios;
#endif
/* args.c */
void handle_args(int argc, char *argv[]);
void clean_args();
/* devmap.c */
int dev_map_read(char *fname);
......@@ -227,26 +203,24 @@ struct devmap *dev_map_find(__u32 device);
void dev_map_exit(void);
/* devs.c */
#if defined(DEBUG)
void dump_rb_trees(void);
#endif
void init_dev_heads(void);
struct d_info *dip_add(__u32 device, struct io *iop);
void dip_rem(struct io *iop);
struct d_info *__dip_find(__u32 device);
void dip_foreach_list(struct io *iop, enum iop_type type, struct list_head *hd);
void dip_foreach(struct io *iop, enum iop_type type,
void dip_foreach(struct io *iop, enum iop_type type,
void (*fnc)(struct io *iop, struct io *this), int rm_after);
struct io *dip_find_sec(struct d_info *dip, enum iop_type type, __u64 sec);
void dip_foreach_out(void (*func)(struct d_info *, void *), void *arg);
void dip_plug(__u32 dev, double cur_time);
void dip_unplug(__u32 dev, double cur_time, int is_timer);
void dip_unplug(__u32 dev, double cur_time, __u64 nio_ups);
void dip_unplug_tm(__u32 dev, __u64 nio_ups);
void dip_exit(void);
/* dip_rb.c */
int rb_insert(struct rb_root *root, struct io *iop);
struct io *rb_find_sec(struct rb_root *root, __u64 sec);
void rb_foreach(struct rb_node *n, struct io *iop,
void rb_foreach(struct rb_node *n, struct io *iop,
void (*fnc)(struct io *iop, struct io *this),
struct list_head *head);
......@@ -338,6 +312,7 @@ int ready_issue(struct io *d_iop, struct io *c_iop);
void trace_issue(struct io *d_iop);
/* trace_plug.c */
__u64 get_nio_up(struct io *u_iop);
void trace_plug(struct io *p_iop);
void trace_unplug_io(struct io *u_iop);
void trace_unplug_timer(struct io *u_iop);
......
......@@ -19,6 +19,12 @@
*
*/
static inline int remapper_dev(__u32 dev)
{
int mjr = MAJOR(dev);
return mjr == 9 || mjr == 253 || mjr == 254;
}
static inline void region_init(struct region_info *reg)
{
INIT_LIST_HEAD(&reg->qranges);
......@@ -118,55 +124,27 @@ static inline void update_lq(__u64 *last_q, struct avg_info *avg, __u64 time)
static inline void dip_update_q(struct d_info *dip, struct io *iop)
{
update_lq(&dip->last_q, &dip->avgs.q2q, iop->t.time);
if (remapper_dev(dip->device))
update_lq(&dip->last_q, &dip->avgs.q2q_dm, iop->t.time);
else
update_lq(&dip->last_q, &dip->avgs.q2q, iop->t.time);
update_qregion(&dip->regions, iop->t.time);
}
static inline struct io *io_alloc(void)
{
struct io *iop;
if (!list_empty(&free_ios)) {
iop = list_entry(free_ios.prev, struct io, f_head);
LIST_DEL(&iop->f_head);
# if defined(COUNT_IOS)
nios_reused++;
# endif
}
else {
iop = malloc(sizeof(struct io));
# if defined(COUNT_IOS)
nios_alloced++;
# endif
}
struct io *iop = malloc(sizeof(*iop));
memset(iop, 0, sizeof(struct io));
# if defined(DEBUG)
iop->f_head.next = LIST_POISON1;
# endif
# if defined(COUNT_IOS)
list_add_tail(&iop->cio_head, &cios);
# endif
list_add_tail(&iop->a_head, &all_ios);
return iop;
}
static inline void io_free(struct io *iop)
{
# if defined(COUNT_IOS)
nios_freed++;
LIST_DEL(&iop->cio_head);
# endif
# if defined(DEBUG)
memset(iop, 0, sizeof(*iop));
# endif
list_add_tail(&iop->f_head, &free_ios);
list_del(&iop->a_head);
free(iop);
}
static inline void io_free_all(void)
......@@ -174,8 +152,8 @@ static inline void io_free_all(void)
struct io *iop;
struct list_head *p, *q;
list_for_each_safe(p, q, &free_ios) {
iop = list_entry(p, struct io, f_head);
list_for_each_safe(p, q, &all_ios) {
iop = list_entry(p, struct io, a_head);
free(iop);
}
}
......@@ -194,11 +172,9 @@ static inline int io_setup(struct io *iop, enum iop_type type)
static inline void io_release(struct io *iop)
{
ASSERT(iop->f_head.next == LIST_POISON1);
if (iop->linked)
dip_rem(iop);
if (iop->pdu)
if (iop->pdu)
free(iop->pdu);
io_free(iop);
......@@ -224,44 +200,52 @@ static inline void io_release(struct io *iop)
static inline void update_q2c(struct io *iop, __u64 c_time)
{
# if defined(DEBUG)
if (per_io_ofp)
fprintf(per_io_ofp, "q2c %13.9f\n", BIT_TIME(c_time));
# endif
UPDATE_AVGS(q2c, iop, iop->pip, c_time);
if (remapper_dev(iop->dip->device))
UPDATE_AVGS(q2c_dm, iop, iop->pip, c_time);
else
UPDATE_AVGS(q2c, iop, iop->pip, c_time);
}
static inline void update_q2a(struct io *iop, __u64 a_time)
{
# if defined(DEBUG)
if (per_io_ofp)
fprintf(per_io_ofp, "q2a %13.9f\n", BIT_TIME(a_time));
# endif
UPDATE_AVGS(q2a, iop, iop->pip, a_time);
if (remapper_dev(iop->dip->device))
UPDATE_AVGS(q2a_dm, iop, iop->pip, a_time);
else
UPDATE_AVGS(q2a, iop, iop->pip, a_time);
}
static inline void update_q2i(struct io *iop, __u64 i_time)
static inline void update_q2g(struct io *iop, __u64 g_time)
{
# if defined(DEBUG)
if (per_io_ofp)
fprintf(per_io_ofp, "q2i %13.9f\n", BIT_TIME(i_time));
# endif
UPDATE_AVGS(q2g, iop, iop->pip, g_time);
}
UPDATE_AVGS(q2i, iop, iop->pip, i_time);
static inline void unupdate_q2g(struct io *iop, __u64 g_time)
{
UNUPDATE_AVGS(q2g, iop, iop->pip, g_time);
}
static inline void unupdate_q2i(struct io *iop, __u64 i_time)
static inline void update_g2i(struct io *iop, __u64 i_time)
{
UNUPDATE_AVGS(q2i, iop, iop->pip, i_time);
UPDATE_AVGS(g2i, iop, iop->pip, i_time);
}
static inline void update_i2d(struct io *iop, __u64 d_time)
static inline void unupdate_g2i(struct io *iop, __u64 i_time)
{
# if defined(DEBUG)
if (per_io_ofp)
fprintf(per_io_ofp, "i2d %13.9f\n", BIT_TIME(d_time));
# endif