Commit 0185ae54 authored by Bas Zoetekouw's avatar Bas Zoetekouw Committed by Dmitry Smirnov

Imported Debian snapshot 0~git-20070306202522-1

parent 7f37c38c
......@@ -5,7 +5,7 @@ PROGS = blkparse blktrace verify_blkparse blkrawverify
LIBS = -lpthread
SCRIPTS = btrace
all: depend $(PROGS) $(SCRIPTS)
all: $(PROGS) $(SCRIPTS)
$(MAKE) -C btt
%.o: %.c
......@@ -23,11 +23,15 @@ verify_blkparse: verify_blkparse.o
blkrawverify: blkrawverify.o
$(CC) $(ALL_CFLAGS) -o $@ $(filter %.o,$^)
$(PROGS): | depend
docs:
$(MAKE) -C doc all
$(MAKE) -C btt docs
docsclean:
$(MAKE) -C doc clean
$(MAKE) -C btt clean
depend:
@$(CC) -MM $(ALL_CFLAGS) *.c 1> .depend
......
......@@ -39,7 +39,7 @@ $ blktrace -d <dev> [ -r debug_path ] [ -o output ] [ -k ] [ -w time ]
[ -a action ] [ -A action mask ]
-d Use specified device. May also be given last after options.
-r Path to mounted debugfs, defaults to /debug.
-r Path to mounted debugfs, defaults to /sys/kernel/debug.
-o File(s) to send output to.
-D Directory to prepend to output file names.
-k Kill running trace.
......@@ -109,13 +109,13 @@ $ blkparse -i <input> [ -o <output> ] [ -b rb_batch ] [ -s ] [ -t ] [ -q ]
-F Format specification. The individual specifiers are:
A - Remap
B - Back merge
B - Bounce
C - Complete
D - Issue
M - Back merge
F - Front merge
G - Get request
I - Insert
M - Both front and back merge
P - Plug
Q - Queue
R - Requeue
......
......@@ -2167,6 +2167,7 @@ static int ms_prime(struct ms_stream *msp)
1, &pci->fdblock);
if (ret) {
free(ptr);
bit = NULL;
goto err;
}
......@@ -2307,9 +2308,27 @@ static int handle(struct ms_stream *msp)
return 1;
}
/*
* Check if we need to sanitize the name. We allow 'foo', or if foo.blktrace.X
* is given, then strip back down to 'foo' to avoid missing files.
*/
static int name_fixup(char *name)
{
char *b;
if (!name)
return 1;
b = strstr(name, ".blktrace.");
if (b)
*b = '\0';
return 0;
}
static int do_file(void)
{
int i, cpu;
int i, cpu, ret;
struct per_dev_info *pdi;
/*
......@@ -2317,6 +2336,10 @@ static int do_file(void)
*/
for (i = 0; i < ndevices; i++) {
pdi = &devices[i];
ret = name_fixup(pdi->name);
if (ret)
return ret;
for (cpu = 0; setup_file(pdi, cpu); cpu++)
;
}
......
......@@ -49,14 +49,7 @@ int add_format_spec(char *option)
return 1;
}
/*
* Set both merges (front and back)
*/
if (spec == 'M') {
override_format['B'] = strdup(option);
override_format['M'] = strdup(option);
} else
override_format[spec] = strdup(option);
override_format[spec] = strdup(option);
return 0;
}
......@@ -335,7 +328,7 @@ static void process_default(char *act, struct per_cpu_info *pci,
case 'D': /* Issue */
case 'I': /* Insert */
case 'Q': /* Queue */
case 'W': /* Bounce */
case 'B': /* Bounce */
if (t->action & BLK_TC_ACT(BLK_TC_PC)) {
char *p;
fprintf(ofp, "%u ", t->bytes);
......@@ -356,9 +349,8 @@ static void process_default(char *act, struct per_cpu_info *pci,
}
break;
case 'B': /* Back merge */
case 'M': /* Back merge */
case 'F': /* Front merge */
case 'M': /* Front or back merge */
case 'G': /* Get request */
case 'S': /* Sleep request */
fprintf(ofp, "%llu + %u [%s]\n", (unsigned long long) t->sector,
......
......@@ -276,7 +276,7 @@ int main(int argc, char *argv[])
{
char *devname;
struct stat st;
int i, cpu, nbad;
int i, cpu, nbad, rval = 0;
FILE *ofp;
char *ofname = malloc(1024);
char *fname = malloc(1024);
......@@ -299,8 +299,10 @@ int main(int argc, char *argv[])
break;
printf(" CPU %d ", cpu); fflush(stdout);
nbad = process(&ofp, devname, fname, cpu);
if (nbad)
if (nbad) {
printf("-- %d bad", nbad);
rval = 1;
}
printf("\n");
}
if (ofp) {
......@@ -309,5 +311,5 @@ int main(int argc, char *argv[])
}
}
return 0;
return rval;
}
......@@ -60,7 +60,7 @@ static char blktrace_version[] = "0.99.2";
#define DEBUGFS_TYPE 0x64626720
#define S_OPTS "d:a:A:r:o:kw:Vb:n:D:lh:p:s"
#define S_OPTS "d:a:A:r:o:kw:Vb:n:D:lh:p:sI:"
static struct option l_opts[] = {
{
.name = "dev",
......@@ -68,6 +68,12 @@ static struct option l_opts[] = {
.flag = NULL,
.val = 'd'
},
{
.name = "input-devs",
.has_arg = required_argument,
.flag = NULL,
.val = 'I'
},
{
.name = "act-mask",
.has_arg = required_argument,
......@@ -1749,9 +1755,9 @@ static int net_setup_client(void)
static char usage_str[] = \
"-d <dev> [ -r debugfs path ] [ -o <output> ] [-k ] [ -w time ]\n" \
"[ -a action ] [ -A action mask ] [ -v ]\n\n" \
"[ -a action ] [ -A action mask ] [ -I <devs file> ] [ -v ]\n\n" \
"\t-d Use specified device. May also be given last after options\n" \
"\t-r Path to mounted debugfs, defaults to /debug\n" \
"\t-r Path to mounted debugfs, defaults to /sys/kernel/debug\n" \
"\t-o File(s) to send output to\n" \
"\t-D Directory to prepend to output file names\n" \
"\t-k Kill a running trace\n" \
......@@ -1764,6 +1770,7 @@ static char usage_str[] = \
"\t-h Run in network client mode, connecting to the given host\n" \
"\t-p Network port to use (default 8462)\n" \
"\t-s Make the network client NOT use sendfile() to transfer data\n" \
"\t-I Add devices found in <devs file>\n" \
"\t-V Print program version info\n\n";
static void show_usage(char *program)
......@@ -1807,6 +1814,24 @@ int main(int argc, char *argv[])
return 1;
break;
case 'I': {
char dev_line[256];
FILE *ifp = fopen(optarg, "r");
if (!ifp) {
fprintf(stderr,
"Invalid file for devices %s\n",
optarg);
return 1;
}
while (fscanf(ifp, "%s\n", dev_line) == 1)
if (resize_devices(strdup(dev_line)) != 0)
return 1;
break;
}
case 'r':
debugfs_path = optarg;
break;
......
CC = gcc
CFLAGS = -Wall -O2 -W -g
#CFLAGS = -Wall -g -W -UDO_INLINE -DDEBUG
# CFLAGS = -Wall -g -W -UDO_INLINE -DDEBUG
ALL_CFLAGS = $(CFLAGS) -I.. -D_GNU_SOURCE -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64
PROGS = btt
#ELIBS = -lefence
......@@ -8,7 +8,8 @@ PROGS = btt
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
trace_issue.o trace_queue.o trace_remap.o trace_requeue.o rbtree.o \
mmap.o trace_plug.o
all: depend $(PROGS)
......@@ -18,7 +19,7 @@ rbtree.o: ../rbtree.c
depend:
@$(CC) -MM $(ALL_CFLAGS) -I.. *.c 1> .depend
clean:
clean: docsclean
-rm -f *.o $(PROGS) .depend
%.o: %.c
......@@ -27,6 +28,12 @@ clean:
btt: $(OBJS)
$(CC) $(ALL_CFLAGS) -o $@ $(filter %.o,$^) $(LIBS)
docs:
$(MAKE) -C doc all
docsclean:
$(MAKE) -C doc clean
ifneq ($(wildcard .depend),)
include .depend
endif
......@@ -27,8 +27,14 @@
#include <fcntl.h>
#include "globals.h"
#define S_OPTS "d:D:e:hi:I:l:M:o:p:q:s:S:t:T:Vv"
#define S_OPTS "Ad:D:e:hi:I:l:M:o:p:q:s:S:t:T:Vv"
static struct option l_opts[] = {
{
.name = "all-data",
.has_arg = no_argument,
.flag = NULL,
.val = 'A'
},
{
.name = "range-delta",
.has_arg = required_argument,
......@@ -137,7 +143,8 @@ static struct option l_opts[] = {
};
static char usage_str[] = \
"\n[ -d <seconds> | --range-delta=<seconds> ]\n" \
"\n[ -A | --all-data ]\n" \
"[ -d <seconds> | --range-delta=<seconds> ]\n" \
"[ -D <dev;...> | --devices=<dev;...> ]\n" \
"[ -e <exe,...> | --exes=<exe,...> ]\n" \
"[ -h | --help ]\n" \
......@@ -167,6 +174,9 @@ void handle_args(int argc, char *argv[])
while ((c = getopt_long(argc, argv, S_OPTS, l_opts, NULL)) != -1) {
switch (c) {
case 'A':
output_all_data = 1;
break;
case 'd':
sscanf(optarg, "%lf", &range_delta);
break;
......@@ -235,11 +245,7 @@ void handle_args(int argc, char *argv[])
exit(1);
}
ifd = open(input_name, O_RDONLY);
if (ifd < 0) {
perror(input_name);
exit(1);
}
setup_ifile(input_name);
if (output_name == NULL)
ranges_ofp = avgs_ofp = stdout;
......@@ -273,6 +279,7 @@ void handle_args(int argc, char *argv[])
perror(iostat_name);
exit(1);
}
setbuffer(iostat_ofp, malloc(64 * 1024), 64 * 1024);
}
if (per_io_name != NULL) {
......@@ -281,5 +288,6 @@ void handle_args(int argc, char *argv[])
perror(per_io_name);
exit(1);
}
setbuffer(per_io_ofp, malloc(64 * 1024), 64 * 1024);
}
}
......@@ -21,14 +21,16 @@
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/time.h>
#include <time.h>
#include "globals.h"
char bt_timeline_version[] = "0.99";
char bt_timeline_version[] = "0.99.1";
char *devices, *exes, *input_name, *output_name, *seek_name;
char *d2c_name, *q2c_name, *per_io_name;
FILE *ranges_ofp, *avgs_ofp, *per_io_ofp;
int ifd, verbose, done, time_bounded;
int verbose, done, time_bounded, output_all_data;
double t_astart, t_aend;
unsigned long n_traces;
struct avgs_info all_avgs;
......@@ -37,9 +39,11 @@ time_t genesis, last_vtrace;
LIST_HEAD(all_devs);
LIST_HEAD(all_procs);
LIST_HEAD(free_ios);
__u64 q_histo[N_HIST_BKTS], d_histo[N_HIST_BKTS];
double range_delta = 0.1;
__u64 last_q = (__u64)-1;
__u64 next_retry_check = 0;
struct region_info all_regions = {
.qranges = LIST_HEAD_INIT(all_regions.qranges),
......@@ -48,6 +52,10 @@ struct region_info all_regions = {
.cr_cur = NULL
};
#if defined(DEBUG)
int rb_tree_size;
#endif
int process(void);
int main(int argc, char *argv[])
......@@ -62,28 +70,28 @@ int main(int argc, char *argv[])
return 0;
}
static inline double tv2dbl(struct timeval *tv)
{
return (double)tv->tv_sec + (((double)tv->tv_usec) / (1000.0 * 1000.0));
}
int process(void)
{
int ret = 0;
struct blk_io_trace *t;
struct io *iop = io_alloc();
struct timeval tvs, tvi, tve;
genesis = last_vtrace = time(NULL);
while (!done && !do_read(ifd, &iop->t, sizeof(struct blk_io_trace))) {
t = convert_to_cpu(&iop->t);
if (t->pdu_len > 0) {
iop->pdu = malloc(t->pdu_len);
if (do_read(ifd, iop->pdu, t->pdu_len)) {
ret = 1;
break;
}
}
gettimeofday(&tvs, NULL);
while (!done && next_trace(&iop->t, &iop->pdu)) {
add_trace(iop);
iop = io_alloc();
}
io_release(iop);
do_retries();
do_retries(0);
gettimeofday(&tvi, NULL);
if (iostat_ofp) {
fprintf(iostat_ofp, "\n");
......@@ -92,11 +100,21 @@ int process(void)
seek_clean();
latency_clean();
gettimeofday(&tve, NULL);
if (verbose) {
double tps = (double)n_traces /
(double)((time(NULL) + 1) - genesis);
printf("%10lu traces @ %.1lf Ktps\n", n_traces, tps/1000.0);
double tps, dt_input = tv2dbl(&tvi) - tv2dbl(&tvs);
tps = (double)n_traces / dt_input;
printf("%10lu traces @ %.1lf Ktps\t%.6lf+%.6lf=%.6lf\n",
n_traces, tps/1000.0,
dt_input, tv2dbl(&tve) - tv2dbl(&tvi),
tv2dbl(&tve) - tv2dbl(&tvs));
#if defined(DEBUG)
printf("\ttree = |%d|\n", rb_tree_size);
if (rb_tree_size > 0)
dump_rb_trees();
#endif
}
return ret;
......
......@@ -25,6 +25,55 @@
#define DEV_HASH(dev) ((MAJOR(dev) ^ MINOR(dev)) & (N_DEV_HASH - 1))
struct list_head dev_heads[N_DEV_HASH];
#if defined(DEBUG)
void __dump_rb_node(struct rb_node *n)
{
struct io *iop = rb_entry(n, struct io, rb_node);
dbg_ping();
if (iop->type == IOP_A)
__dump_iop2(stdout, iop, bilink_first_down(iop, NULL));
else
__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++) {
if (type != IOP_L)
__dump_rb_tree(dip, type);
}
}
}
}
#endif
void init_dev_heads(void)
{
int i;
......@@ -34,8 +83,8 @@ void init_dev_heads(void)
struct d_info *__dip_find(__u32 device)
{
struct list_head *p;
struct d_info *dip;
struct list_head *p;
__list_for_each(p, &dev_heads[DEV_HASH(device)]) {
dip = list_entry(p, struct d_info, hash_head);
......@@ -52,6 +101,7 @@ struct d_info *dip_add(__u32 device, struct io *iop)
if (dip == NULL) {
dip = malloc(sizeof(struct d_info));
memset(dip, 0, sizeof(*dip));
dip->heads = dip_rb_mkhds();
init_region(&dip->regions);
dip->device = device;
......@@ -59,20 +109,36 @@ struct d_info *dip_add(__u32 device, struct io *iop)
dip->map = dev_map_find(device);
dip->seek_handle = seeki_init(device);
latency_init(dip);
memset(&dip->stats, 0, sizeof(dip->stats));
memset(&dip->all_stats, 0, sizeof(dip->all_stats));
list_add_tail(&dip->hash_head, &dev_heads[DEV_HASH(device)]);
list_add_tail(&dip->all_head, &all_devs);
dip->start_time = BIT_TIME(iop->t.time);
dip->pre_culling = 1;
n_devs++;
}
if (dip->pre_culling) {
if (iop->type == IOP_Q || iop->type == IOP_A)
dip->pre_culling = 0;
else
return NULL;
}
iop->linked = dip_rb_ins(dip, iop);
#if defined(DEBUG)
if (iop->linked)
rb_tree_size++;
#endif
dip->end_time = BIT_TIME(iop->t.time);
return dip;
}
void dip_rem(struct io *iop)
{
dip_rb_rem(iop);
if (iop->linked) {
dip_rb_rem(iop);
iop->linked = 0;
}
}
void dip_foreach(struct io *iop, enum iop_type type,
......@@ -128,3 +194,26 @@ void dip_foreach_out(void (*func)(struct d_info *, void *), void *arg)
}
}
}
void dip_plug(__u32 dev, double cur_time)
{
struct d_info *dip = __dip_find(dev);
if (!dip || dip->is_plugged) return;
dip->is_plugged = 1;
dip->last_plug = cur_time;
}
void dip_unplug(__u32 dev, double cur_time, int is_timer)
{
struct d_info *dip = __dip_find(dev);
if (!dip || !dip->is_plugged) return;
dip->nplugs++;
if (is_timer) dip->n_timer_unplugs++;
dip->plugged_time += (cur_time - dip->last_plug);
dip->is_plugged = 0;
}
......@@ -76,7 +76,10 @@ 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) list_add_tail(&this->f_head, head);
if (head) {
ASSERT(this->f_head.next == LIST_POISON1);
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
all: btt.pdf
btt.tex: activity.eps qhist.eps dhist.eps seek.eps
@touch btt.tex
btt.pdf: btt.tex
@latex btt.tex
@latex btt.tex
@dvipdfm -p a4 btt
@rm -rf $(DOCTMP)
clean:
-rm -f btt.pdf $(DOCTMP)
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -27,6 +27,16 @@
#include "rbtree.h"
#include "list.h"
/*
* 0 == 1 blk
* 1 == 2 blks
* ...
* 1022 == 1023 blks
* 1023 == 1024 blks
* 1024 == > 1024 blks
*/
#define N_HIST_BKTS 1025
#define BIT_TIME(t) ((double)SECONDS(t) + ((double)NANO_SECONDS(t) / 1.0e9))
#define BIT_START(iop) ((iop)->t.sector)
......@@ -52,9 +62,9 @@
#define ASSERT(truth)
#define DBG_PING()
#define LIST_DEL(hp) do { \
if (((hp)->next != NULL) && \
((hp)->next != LIST_POISON1)) \
list_del(hp); \
ASSERT((hp)->next != NULL); \
ASSERT(!list_empty(hp)); \
list_del(hp); \
} while (0)
#endif
......@@ -62,14 +72,14 @@ enum iop_type {
IOP_Q = 0,
IOP_X = 1,
IOP_A = 2,
IOP_L = 3, // Betwen-device linkage
IOP_I = 3,
IOP_M = 4,
IOP_I = 5,
IOP_D = 6,
IOP_C = 7,
IOP_R = 8,
IOP_D = 5,
IOP_C = 6,
IOP_R = 7,
IOP_L = 8, // IOP_A -> IOP_A + IOP_L
};
#define N_IOP_TYPES (IOP_R + 1)
#define N_IOP_TYPES (IOP_L + 1)
struct file_info {
struct file_info *next;
......@@ -155,21 +165,28 @@ struct d_info {
struct stats stats, all_stats;
__u64 last_q, n_ds;
__u32 device;
int pre_culling;
int is_plugged, nplugs, n_timer_unplugs;
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, c_pending, retry;
struct list_head down_list, up_list;
struct d_info *dip;
struct p_info *pip;
struct blk_io_trace t;
void *pdu;
struct blk_io_trace t;
__u64 bytes_left;
int linked, on_retry_list, down_len, up_len;
enum iop_type type;
};
struct list_head down_head, up_head, c_pending, retry;
struct list_head down_list, up_list;
__u64 bytes_left;
int run_ready, linked, self_remap, displayed, on_retry_list;
struct bilink {
struct list_head down_head, up_head;
struct io *diop, *uiop;
};
/* bt_timeline.c */
......@@ -178,17 +195,21 @@ 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 double range_delta;
extern FILE *ranges_ofp, *avgs_ofp, *iostat_ofp, *per_io_ofp;;
extern int verbose, ifd, dump_level, done, time_bounded;
extern int verbose, done, time_bounded, output_all_data;
extern unsigned int n_devs;
extern unsigned long n_traces;
extern struct list_head all_devs, all_procs, retries;
extern struct avgs_info all_avgs;
extern __u64 last_q;
extern __u64 last_q, next_retry_check;
extern struct region_info all_regions;
extern struct list_head 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
/* args.c */
void handle_args(int argc, char *argv[]);
......@@ -198,6 +219,9 @@ int dev_map_read(char *fname);
struct devmap *dev_map_find(__u32 device);
/* 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);
......@@ -207,6 +231,8 @@ 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);
/* dip_rb.c */
int rb_insert(struct rb_root *root, struct io *iop);
......@@ -232,13 +258,16 @@ void latency_d2c(struct d_info *dip, __u64 tstamp, __u64 latency);
void latency_q2c(struct d_info *dip, __u64 tstamp, __u64 latency);
/* misc.c */
struct blk_io_trace *convert_to_cpu(struct blk_io_trace *t);
int in_devices(struct blk_io_trace *t);
unsigned int do_read(int ifd, void *buf, int len);
void add_file(struct file_info **fipp, FILE *fp, char *oname);
void clean_files(struct file_info **fipp);
void dbg_ping(void);
/* mmap.c */