[PATCH] Added iostat-style statistics to btt
[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
25 #include "blktrace.h"
26 #include "list.h"
27
28 #define pdu_start(t)    (((void *) (t) + sizeof(struct blk_io_trace)))
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 #if defined(DEBUG)
38 #define ASSERT(truth)   do {                                            \
39                                 if (!(truth)) {                         \
40                                         DBG_PING();                     \
41                                         assert(truth);                  \
42                                 }                                       \
43                         } while (0)
44
45 #define DBG_PING()              dbg_ping()
46
47 #define LIST_DEL(hp)    list_del(hp)
48
49 #else
50 #define ASSERT(truth)
51 #define DBG_PING()
52
53 #define LIST_DEL(hp)    do {                                            \
54                                 if (((hp)->next != NULL) &&             \
55                                     ((hp)->next != LIST_POISON1))       \
56                                         list_del(hp);                   \
57                         } while (0)
58 #endif
59
60 #define IO_ZALLOC()     my_zmalloc(&free_ios, sizeof(struct io))
61 #define IO_FREE(iop)    my_free(&free_ios, iop)
62
63 enum iop_type {
64         IOP_Q = 0,
65         IOP_X = 1,
66         IOP_A = 2,
67         IOP_M = 3,
68         IOP_I = 4,
69         IOP_D = 5,
70         IOP_C = 6,
71         IOP_Y = 7,
72 };
73 #define N_IOP_TYPES     (IOP_Y + 1)
74
75 struct my_mem {
76         struct my_mem *next;
77 };
78
79 struct io;
80 struct io_list {
81         struct list_head head;
82         struct io *iop;
83         int cy_users;
84 };
85
86 struct avg_info {
87         __u64 min, max, total;
88         double avg;
89         int n;
90 };
91
92 struct avgs_info {
93         struct avg_info q2q;
94         struct avg_info q2c;
95         struct avg_info q2a;            /* Q to (A or X) */
96         struct avg_info q2i;            /* Q to (I or M) */
97         struct avg_info i2d;            /* (I or M) to D */
98         struct avg_info d2c;
99
100         struct avg_info blks;           /* Blocks transferred */
101 };
102
103 struct range_info {
104         struct list_head head;          /* on: qranges OR cranges */
105         __u64 start, end;
106 };
107
108 struct region_info {
109         struct list_head qranges;
110         struct list_head cranges;
111         struct range_info *qr_cur, *cr_cur;
112 };
113
114 struct p_info;
115 struct p_pid {
116         struct list_head head;
117         struct p_info *pip;
118         __u32 pid;
119 };
120
121 struct p_info {
122         struct list_head head;
123         struct region_info regions;
124         struct avgs_info avgs;
125         char *name;
126         __u64 last_q;
127 };
128
129 struct devmap {
130         struct devmap *next;
131         char device[32];
132         char model[64];
133         unsigned int host, bus, target, lun;
134         char node[32], pci[32];
135         unsigned int irq, cpu;
136         char devno[32];
137 };
138
139 struct stats {
140         __u64 rqm[2];
141         __u64 ios[2];
142         __u64 sec[2];
143         __u64 wait;
144         __u64 svctm;
145
146         int cur_qusz, cur_dev;
147         double last_qu_change, last_dev_change, tot_qusz, idle_time;
148 };
149
150 struct d_info {
151         struct list_head head, hash_head;
152         struct list_head iop_heads[N_IOP_TYPES];
153         struct region_info regions;
154         struct avgs_info avgs;
155         __u64 last_q;
156         __u32 device;
157         __u64 n_ds;
158         struct devmap *map;
159         void *seek_handle;
160         struct stats stats, all_stats;
161 };
162
163 struct io {
164         struct list_head all_head, dev_head;
165         struct d_info *dip;
166         struct p_info *pip;
167         void *pdu;
168
169         struct blk_io_trace t;
170
171         int users, traversed;
172         enum iop_type type;
173
174         union {
175                 struct {
176                         union {
177                                 struct io *q_a;
178                                 struct io *q_x;
179                         } qp;
180                         enum {
181                                 Q_NONE = 10,
182                                 Q_A = 20,
183                                 Q_X = 30,
184                         } qp_type;
185                 }                                         q;
186                 struct {
187                         union {
188                                 struct io *a_q;
189                                 struct io *a_a;
190                         } ap;
191                         enum {
192                                 A_NONE = 10,
193                                 A_A = 20,
194                                 A_Q = 30,
195                         } ap_type;
196                 }                                         a;
197                 struct { struct io *x_q;                } x;
198                 struct { struct io *m_q;                } m;
199                 struct { struct list_head i_qs_head;    } i;
200                 struct { struct list_head d_im_head;    } d;
201                 struct { struct io *c_d;                } c;
202                 struct { struct io *y_c1, *y_c2;        } y;
203         } u;
204 };
205
206 extern char bt_timeline_version[], *devices, *exes, *input_name, *output_name;
207 extern char *seek_name, *iostat_name;
208 extern double range_delta;
209 extern FILE *ranges_ofp, *avgs_ofp, *iostat_ofp;
210 extern int is_lvm, verbose, ifd;
211 extern unsigned int n_devs;
212 extern unsigned long n_traces, n_io_allocs, n_io_frees;
213 extern struct list_head all_devs, all_ios, all_procs;
214 extern struct avgs_info all_avgs;
215 extern __u64 last_q;
216 extern struct region_info all_regions;
217 extern struct my_mem *free_ios, *free_bits;
218 extern char iop_map[];
219 extern unsigned int pending_xs;
220 extern __u64 iostat_interval, iostat_last_stamp;
221
222 void add_trace(struct io *iop);
223 int in_devices(struct blk_io_trace *t);
224 char *make_dev_hdr(char *pad, size_t len, struct d_info *dip);
225 int output_avgs(FILE *ofp);
226 int output_ranges(FILE *ofp);
227 unsigned int do_read(int ifd, void *buf, int len);
228 void add_process(__u32 pid, char *name);
229 struct p_info *find_process(__u32 pid, char *name);
230 void pip_update_q(struct io *iop);
231 void handle_args(int argc, char *argv[]);
232 struct devmap *dev_map_find(__u32 device);
233 int dev_map_read(char *fname);
234 void add_cy(struct io *iop);
235 void rem_c(struct io *iop);
236 void cy_init(void);
237 void cy_shutdown(void);
238 struct d_info *__dip_find(__u32 device);
239 struct d_info *dip_add(__u32 device, struct io *iop);
240 void traverse(struct io *iop);
241 void io_free_resources(struct io *iop);
242 void *seeki_init(__u32 device);
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, long long **modes_p, int *nseeks_p);
248
249 void iostat_init(void);
250 void iostat_insert(struct io *iop);
251 void iostat_merge(struct io *iop);
252 void iostat_issue(struct io *iop);
253 void iostat_complete(struct io *iop);
254 void iostat_check_time(__u64 stamp);
255 void iostat_dump_stats(__u64 stamp, int all);
256
257 #include "inlines.h"