[PATCH] Convert to using on-the-fly RB trees, no post-traversal.
[blktrace.git] / btt / globals.h
1 /*
2  * blktrace output analysis: generate a timeline & gather statistics
3  *
4  * Copyright (C) 2006 Alan D. Brunelle <Alan.Brunelle@hp.com>
5  *
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 2 of the License, or
9  *  (at your option) any later version.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  */
21 #include <assert.h>
22 #include <stdio.h>
23 #include <string.h>
24 #include <time.h>
25
26 #include "blktrace.h"
27 #include "rbtree.h"
28 #include "list.h"
29
30 #define BIT_TIME(t)     ((double)SECONDS(t) + ((double)NANO_SECONDS(t) / 1.0e9))
31
32 #define BIT_START(iop)  ((iop)->t.sector)
33 #define BIT_END(iop)    ((iop)->t.sector + ((iop)->t.bytes >> 9))
34 #define IOP_READ(iop)   ((iop)->t.action & BLK_TC_ACT(BLK_TC_READ))
35 #define IOP_RW(iop)     (IOP_READ(iop) ? 1 : 0)
36
37 #define TO_SEC(nanosec) ((double)(nanosec) / 1.0e9)
38 #define TO_MSEC(nanosec) (1000.0 * TO_SEC(nanosec))
39
40 #if defined(DEBUG)
41 #define DBG_PING()      dbg_ping()
42 #define ASSERT(truth)   do {                                            \
43                                 if (!(truth)) {                         \
44                                         DBG_PING();                     \
45                                         assert(truth);                  \
46                                 }                                       \
47                         } while (0)
48
49
50 #define LIST_DEL(hp)    list_del(hp)
51 #else
52 #define ASSERT(truth)
53 #define DBG_PING()
54 #define LIST_DEL(hp)    do {                                            \
55                                 if (((hp)->next != NULL) &&             \
56                                     ((hp)->next != LIST_POISON1))       \
57                                         list_del(hp);                   \
58                         } while (0)
59 #endif
60
61 enum iop_type {
62         IOP_Q = 0,
63         IOP_X = 1,
64         IOP_A = 2,
65         IOP_M = 3,
66         IOP_I = 4,
67         IOP_D = 5,
68         IOP_C = 6,
69         IOP_R = 7,
70 };
71 #define N_IOP_TYPES     (IOP_R + 1)
72
73 struct file_info {
74         struct file_info *next;
75         FILE *ofp;
76         char oname[1];
77 };
78
79 struct mode {
80         int most_seeks, nmds;
81         long long *modes;
82 };
83
84 struct io;
85 struct io_list {
86         struct list_head head;
87         struct io *iop;
88         int cy_users;
89 };
90
91 struct avg_info {
92         __u64 min, max, total;
93         double avg;
94         int n;
95 };
96
97 struct avgs_info {
98         struct avg_info q2q;
99         struct avg_info q2c;
100         struct avg_info q2a;            /* Q to (A or X) */
101         struct avg_info q2i;            /* Q to (I or M) */
102         struct avg_info i2d;            /* (I or M) to D */
103         struct avg_info d2c;
104
105         struct avg_info blks;           /* Blocks transferred */
106 };
107
108 struct range_info {
109         struct list_head head;          /* on: qranges OR cranges */
110         __u64 start, end;
111 };
112
113 struct region_info {
114         struct list_head qranges;
115         struct list_head cranges;
116         struct range_info *qr_cur, *cr_cur;
117 };
118
119 struct p_info {
120         struct region_info regions;
121         struct avgs_info avgs;
122         __u64 last_q;
123         __u32 pid;
124         char name[1];
125 };
126
127 struct devmap {
128         struct devmap *next;
129         unsigned int host, bus, target, lun, irq, cpu;
130         char model[64];
131         char device[32], node[32], pci[32], devno[32];
132 };
133
134 struct stats {
135         __u64 rqm[2], ios[2], sec[2], wait, svctm;
136         double last_qu_change, last_dev_change, tot_qusz, idle_time;
137         int cur_qusz, cur_dev;
138 };
139
140 struct d_info {
141         struct list_head all_head, hash_head;
142         void *heads;
143         struct region_info regions;
144         struct devmap *map;
145         void *seek_handle;
146         FILE *d2c_ofp, *q2c_ofp;
147         struct avgs_info avgs;
148         struct stats stats, all_stats;
149         __u64 last_q, n_ds;
150         __u32 device;
151 };
152
153 struct io {
154         struct rb_node rb_node;
155         struct list_head f_head;
156         struct d_info *dip;
157         struct p_info *pip;
158         struct blk_io_trace t;
159         void *pdu;
160         enum iop_type type;
161         int linked;
162 };
163
164 /* bt_timeline.c */
165
166 extern char bt_timeline_version[], *devices, *exes, *input_name, *output_name;
167 extern char *seek_name, *iostat_name, *d2c_name, *q2c_name;
168 extern double range_delta;
169 extern FILE *ranges_ofp, *avgs_ofp, *iostat_ofp;
170 extern int verbose, ifd;
171 extern unsigned int n_devs;
172 extern unsigned long n_traces;
173 extern struct list_head all_devs, all_procs;
174 extern struct avgs_info all_avgs;
175 extern __u64 last_q;
176 extern struct region_info all_regions;
177 extern struct list_head free_ios;
178 extern __u64 iostat_interval, iostat_last_stamp;
179 extern time_t genesis, last_vtrace;
180
181 /* args.c */
182 void handle_args(int argc, char *argv[]);
183
184 /* dev_map.c */
185 int dev_map_read(char *fname);
186 struct devmap *dev_map_find(__u32 device);
187
188 /* devs.c */
189 void init_dev_heads(void);
190 struct d_info *dip_add(__u32 device, struct io *iop, int link);
191 void dip_rem(struct io *iop);
192 struct d_info *__dip_find(__u32 device);
193 void dip_foreach(struct io *iop, enum iop_type type, 
194                  void (*fnc)(struct io *iop, struct io *this), int rm_after);
195 struct io *dip_find_sec(struct d_info *dip, enum iop_type type, __u64 sec);
196 void dip_foreach_out(void (*func)(struct d_info *, void *), void *arg);
197
198 /* dip_rb.c */
199 void rb_insert(struct rb_root *root, struct io *iop);
200 struct io *rb_find_sec(struct rb_root *root, __u64 sec);
201 void rb_foreach(struct rb_node *n, struct io *iop, 
202                       void (*fnc)(struct io *iop, struct io *this),
203                       struct list_head *head);
204
205 /* iostat.c */
206 void iostat_init(void);
207 void iostat_insert(struct io *iop);
208 void iostat_merge(struct io *iop);
209 void iostat_issue(struct io *iop);
210 void iostat_unissue(struct io *iop);
211 void iostat_complete(struct io *d_iop, struct io *c_iop);
212 void iostat_check_time(__u64 stamp);
213 void iostat_dump_stats(__u64 stamp, int all);
214
215 /* latency.c */
216 void latency_init(struct d_info *dip);
217 void latency_clean(void);
218 void latency_d2c(struct d_info *dip, __u64 tstamp, __u64 latency);
219 void latency_q2c(struct d_info *dip, __u64 tstamp, __u64 latency);
220
221 /* misc.c */
222 struct blk_io_trace *convert_to_cpu(struct blk_io_trace *t);
223 int in_devices(struct blk_io_trace *t);
224 unsigned int do_read(int ifd, void *buf, int len);
225 void add_file(struct file_info **fipp, FILE *fp, char *oname);
226 void clean_files(struct file_info **fipp);
227 void dbg_ping(void);
228
229 /* output.c */
230 int output_avgs(FILE *ofp);
231 int output_ranges(FILE *ofp);
232 char *make_dev_hdr(char *pad, size_t len, struct d_info *dip);
233
234 /* proc.c */
235 void add_process(__u32 pid, char *name);
236 struct p_info *find_process(__u32 pid, char *name);
237 void pip_update_q(struct io *iop);
238 void pip_foreach_out(void (*f)(struct p_info *, void *), void *arg);
239
240 /* seek.c */
241 void *seeki_init(__u32 device);
242 void seek_clean(void);
243 void seeki_add(void *handle, struct io *iop);
244 double seeki_mean(void *handle);
245 long long seeki_nseeks(void *handle);
246 long long seeki_median(void *handle);
247 int seeki_mode(void *handle, struct mode *mp);
248
249 /* trace.c */
250 void add_trace(struct io *iop);
251
252 #include "inlines.h"