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)
}
buf = malloc(SETBUFFER_SIZE);
- assert(buf);
setbuffer(ofp, buf, SETBUFFER_SIZE);
add_file(&arg_files, ofp, fname);
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));
}
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];
.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[])
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();
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;
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;
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;
}
}
}
-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) {
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);
}
}
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++;
}
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);
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)
{
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);
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
-#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#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,
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;
int linked;
enum iop_type type;
-
-#if defined(COUNT_IOS)
- struct list_head cio_head;
-#endif
};
/* bt_timeline.c */
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 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);
/* 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);
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)
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);
}
}
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);
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
if (remapper_dev(iop->dip->device))
UPDATE_AVGS(q2c_dm, iop, iop->pip, c_time);
else
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
if (remapper_dev(iop->dip->device))
UPDATE_AVGS(q2a_dm, iop, iop->pip, a_time);
else
static inline void update_q2g(struct io *iop, __u64 g_time)
{
-# if defined(DEBUG)
- if (per_io_ofp)
- fprintf(per_io_ofp, "q2g %13.9f\n", BIT_TIME(g_time));
-# endif
-
UPDATE_AVGS(q2g, iop, iop->pip, g_time);
}
static inline void update_g2i(struct io *iop, __u64 i_time)
{
-# if defined(DEBUG)
- if (per_io_ofp)
- fprintf(per_io_ofp, "g2i %13.9f\n", BIT_TIME(i_time));
-# endif
-
UPDATE_AVGS(g2i, iop, iop->pip, i_time);
}
static inline void update_q2m(struct io *iop, __u64 m_time)
{
-# if defined(DEBUG)
- if (per_io_ofp)
- fprintf(per_io_ofp, "q2m %13.9f\n", BIT_TIME(m_time));
-# endif
-
UPDATE_AVGS(q2m, iop, iop->pip, m_time);
}
static inline void update_i2d(struct io *iop, __u64 d_time)
{
-# if defined(DEBUG)
- if (per_io_ofp)
- fprintf(per_io_ofp, "i2d %13.9f\n", BIT_TIME(d_time));
-# endif
-
UPDATE_AVGS(i2d, iop, iop->pip, d_time);
}
static inline void update_m2d(struct io *iop, __u64 d_time)
{
-# if defined(DEBUG)
- if (per_io_ofp)
- fprintf(per_io_ofp, "m2d %13.9f\n", BIT_TIME(d_time));
-# endif
-
UPDATE_AVGS(m2d, iop, iop->pip, d_time);
}
static inline void update_d2c(struct io *iop, __u64 c_time)
{
-# if defined(DEBUG)
- if (per_io_ofp)
- fprintf(per_io_ofp, "d2c %13.9f\n", BIT_TIME(c_time));
-# endif
-
UPDATE_AVGS(d2c, iop, iop->pip, c_time);
}
{
__u64 nblks = iop->t.bytes >> 9;
avg_update(&all_avgs.blks, nblks);
- ASSERT(iop->dip != NULL);
avg_update(&iop->dip->avgs.blks, nblks);
if (iop->pip)
avg_update(&iop->pip->avgs.blks, nblks);
static inline void dip_rb_rem(struct io *iop)
{
rb_erase(&iop->rb_node, __get_root(iop->dip, iop->type));
-
-# if defined(DEBUG)
- rb_tree_size--;
-# endif
}
-static inline void dip_rb_fe(struct d_info *dip, enum iop_type type,
- struct io *iop,
- void (*fnc)(struct io *iop, struct io *this),
+static inline void dip_rb_fe(struct d_info *dip, enum iop_type type,
+ struct io *iop,
+ void (*fnc)(struct io *iop, struct io *this),
struct list_head *head)
{
rb_foreach(__get_root(dip, type)->rb_node, iop, fnc, head);
}
-static inline struct io *dip_rb_find_sec(struct d_info *dip,
+static inline struct io *dip_rb_find_sec(struct d_info *dip,
enum iop_type type, __u64 sec)
{
return rb_find_sec(__get_root(dip, type), sec);
fprintf(ofp, "%5d.%09lu %3d,%-3d %c %10llu+%-4u <- (%3d,%-3d) %10llu\n",
(int)SECONDS(a_iop->t.time),
(unsigned long)NANO_SECONDS(a_iop->t.time),
- MAJOR(a_iop->t.device), MINOR(a_iop->t.device),
- type2c(a_iop->type), (unsigned long long)a_iop->t.sector,
- t_sec(&a_iop->t), MAJOR(l_iop->t.device),
+ MAJOR(a_iop->t.device), MINOR(a_iop->t.device),
+ type2c(a_iop->type), (unsigned long long)a_iop->t.sector,
+ t_sec(&a_iop->t), MAJOR(l_iop->t.device),
MINOR(l_iop->t.device), (unsigned long long)l_iop->t.sector);
}
{
if (dip->stats.cur_dev == 0 || force) {
dip->stats.idle_time += (now - dip->stats.last_dev_change);
- dip->all_stats.idle_time +=
+ dip->all_stats.idle_time +=
(now - dip->all_stats.last_dev_change);
}
dip->stats.last_dev_change = dip->all_stats.last_dev_change = now;
for (;;) {
i = sscanf(p, "%u,%u;", &mjr, &mnr);
- ASSERT(i == 2);
-
if ((mjr == MAJOR(t->device) && (mnr == MINOR(t->device))))
return 1;
free(bip);
}
}
-
+
void dbg_ping(void) {}
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
-#include <assert.h>
#include <sys/mman.h>
#include <string.h>
static inline size_t min_len(size_t a, size_t b) { return a < b ? a : b; }
-static inline size_t convert_to_cpu(struct blk_io_trace *t,
- struct blk_io_trace *tp,
+static inline size_t convert_to_cpu(struct blk_io_trace *t,
+ struct blk_io_trace *tp,
void **pdu)
{
if (data_is_native == -1)
tp->pdu_len = be16_to_cpu(t->pdu_len);
}
- assert(CHECK_MAGIC(tp));
- assert((tp->magic & 0xff) == SUPPORTED_VERSION);
-
if (tp->pdu_len) {
*pdu = malloc(tp->pdu_len);
memcpy(*pdu, t+1, tp->pdu_len);
{
struct seek_mode_info *p, *this, *new_list = NULL;
- ASSERT(sip->head != NULL);
while ((this = sip->head) != NULL) {
sip->head = this->next;
this->next = NULL;
if (new_list == NULL || this->nseeks > new_list->nseeks)
new_list = this;
else if (this->nseeks == new_list->nseeks) {
- assert(this->nseeks == new_list->nseeks);
for (p = new_list; p != NULL; p = p->next)
if (p->mode == this->mode)
break;
p = &(*p)->rb_left;
else if (pid > this->u.pid)
p = &(*p)->rb_right;
- else {
- ASSERT(strcmp(that->name, this->pip->name) == 0);
+ else
return; // Already there
- }
}
this = malloc(sizeof(struct pn_info));
/*
* We're here because we have a pid, and no name, but
- * we didn't find a process ...
+ * we didn't find a process ...
*
* We'll craft one using the pid...
*/
return __find_process_pid(pid);
}
- assert(name != NULL);
return __find_process_name(name);
}
{
if (iop->pip) {
if (remapper_dev(iop->dip->device))
- update_lq(&iop->pip->last_q, &iop->pip->avgs.q2q_dm,
+ update_lq(&iop->pip->last_q, &iop->pip->avgs.q2q_dm,
iop->t.time);
else
- update_lq(&iop->pip->last_q, &iop->pip->avgs.q2q,
+ update_lq(&iop->pip->last_q, &iop->pip->avgs.q2q,
iop->t.time);
update_qregion(&iop->pip->regions, iop->t.time);
}
return sip->total_sectors / sip->tot_seeks;
}
-int __median(struct rb_node *n, long long sofar, long long target, long
+int __median(struct rb_node *n, long long sofar, long long target, long
long *rvp)
{
struct seek_bkt *sbp;
struct seeki *sip = handle;
if (sip->root.rb_node)
- (void)__median(sip->root.rb_node, 0LL, sip->tot_seeks / 2,
+ (void)__median(sip->root.rb_node, 0LL, sip->tot_seeks / 2,
&rval);
return rval;
else if (sbp->nseeks > mp->most_seeks)
mp->nmds = 0;
else if (sbp->nseeks == mp->most_seeks)
- mp->modes = realloc(mp->modes, (mp->nmds + 1) *
+ mp->modes = realloc(mp->modes, (mp->nmds + 1) *
sizeof(long long));
else
return;
struct rb_root *root = &sip->root;
memset(mp, 0, sizeof(struct mode));
- if (root->rb_node)
+ if (root->rb_node)
__mode(root->rb_node, mp);
return mp->nmds;
iostat_check_time(iop->t.time);
if (verbose && ((now - last_vtrace) > 0)) {
-
-# if defined(DEBUG)
- printf("%10lu t\ttree size=|%10d|\r",
- n_traces, rb_tree_size);
-# else
printf("%10lu t\r", n_traces);
-# endif
-
if ((n_traces % 1000000) == 0) printf("\n");
fflush(stdout);
last_vtrace = now;
case __BLK_TA_PLUG: trace_plug(iop); break;
case __BLK_TA_UNPLUG_IO: trace_unplug_io(iop); break;
case __BLK_TA_UNPLUG_TIMER: trace_unplug_timer(iop); break;
- default:
- io_release(iop);
+ default:
+ io_release(iop);
return;
}
}
{
if (iop->t.action & BLK_TC_ACT(BLK_TC_NOTIFY)) {
if (iop->t.action == BLK_TN_PROCESS) {
- if (iop->t.pid == 0)
+ if (iop->t.pid == 0)
add_process(0, "kernel");
else {
char *slash = strchr(iop->pdu, '/');
*/
#include "globals.h"
-static inline void __out(FILE *ofp, __u64 tm, enum iop_type type,
+static inline void __out(FILE *ofp, __u64 tm, enum iop_type type,
__u64 sec, __u32 nsec, int indent)
{
if (tm != (__u64)-1) {
- if (indent)
+ if (indent)
fprintf(ofp, " ");
- fprintf(ofp, "%5d.%09lu %c %10llu+%-4u\n",
+ fprintf(ofp, "%5d.%09lu %c %10llu+%-4u\n",
(int)SECONDS(tm), (unsigned long)NANO_SECONDS(tm),
type2c(type), (unsigned long long)sec, nsec);
}
display_io_track(per_io_ofp, q_iop);
}
- LIST_DEL(&q_iop->f_head);
+ list_del(&q_iop->f_head);
io_release(q_iop);
}
}
dip_foreach_list(d_iop, IOP_Q, &head);
list_for_each_safe(p, q, &head) {
struct io *q_iop = list_entry(p, struct io, f_head);
-
+
if (q_iop->i_time != (__u64)-1)
update_i2d(q_iop, tdelta(q_iop->i_time, d_iop->t.time));
else if (q_iop->m_time != (__u64)-1)
update_m2d(q_iop, tdelta(q_iop->m_time, d_iop->t.time));
d_iop->bytes_left -= q_iop->t.bytes;
- LIST_DEL(&q_iop->f_head);
+ list_del(&q_iop->f_head);
q_iop->d_time = d_iop->t.time;
q_iop->d_sec = d_iop->t.sector;
q_iop->d_nsec = t_sec(&d_iop->t);
if (output_all_data)
- q2d_histo_add(q_iop->dip->q2d_priv,
+ q2d_histo_add(q_iop->dip->q2d_priv,
d_iop->t.time - q_iop->t.time);
}
-
- assert(d_iop->bytes_left == 0);
}
void trace_issue(struct io *d_iop)
update_lq(&last_q, &all_avgs.q2q, q_iop->t.time);
}
- q_iop->i_time = q_iop->g_time = q_iop->i_time = q_iop->m_time =
+ q_iop->i_time = q_iop->g_time = q_iop->i_time = q_iop->m_time =
q_iop->d_time = (__u64)-1;
q_iop->dip->n_qs++;
{
struct d_info *dip;
- assert(u_iop->t.pdu_len >= sizeof(__u64));
-
dip = __dip_find(u_iop->t.device);
if (dip && dip->unplug_hist_handle) {
__u64 *val = u_iop->pdu;
if (idx > EXCESS_BKT)
idx = EXCESS_BKT;
- assert((0 <= idx) && (idx <= EXCESS_BKT));
hbp->hist[idx]++;
}
}