spelling and grammar fixes for btreplay.tex
[blktrace.git] / btt / inlines.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
22 static inline int remapper_dev(__u32 dev)
23 {
24         int mjr = MAJOR(dev);
25         return mjr == 9 || mjr == 253 || mjr == 254;
26 }
27
28 static inline void region_init(struct region_info *reg)
29 {
30         INIT_LIST_HEAD(&reg->qranges);
31         INIT_LIST_HEAD(&reg->cranges);
32 }
33
34 static inline void __region_exit(struct list_head *range_head)
35 {
36         struct list_head *p, *q;
37         struct range_info *rip;
38
39         list_for_each_safe(p, q, range_head) {
40                 rip = list_entry(p, struct range_info, head);
41                 free(rip);
42         }
43 }
44
45 static inline void region_exit(struct region_info *reg)
46 {
47         __region_exit(&reg->qranges);
48         __region_exit(&reg->cranges);
49 }
50
51 static inline void update_range(struct list_head *head_p, __u64 time)
52 {
53         struct range_info *rip;
54
55         if (!list_empty(head_p)) {
56                 rip = list_entry(head_p->prev, struct range_info, head);
57
58                 if (time < rip->end)
59                         return;
60
61                 if (BIT_TIME(time - rip->end) < range_delta) {
62                         rip->end = time;
63                         return;
64                 }
65         }
66
67         rip = malloc(sizeof(*rip));
68         rip->start = rip->end = time;
69         list_add_tail(&rip->head, head_p);
70 }
71
72 static inline void update_qregion(struct region_info *reg, __u64 time)
73 {
74         update_range(&reg->qranges, time);
75 }
76
77 static inline void update_cregion(struct region_info *reg, __u64 time)
78 {
79         update_range(&reg->cranges, time);
80 }
81
82 static inline void avg_update(struct avg_info *ap, __u64 t)
83 {
84         if (ap->n++ == 0)
85                 ap->min = ap->total = ap->max = t;
86         else {
87                 if (t < ap->min)
88                         ap->min = t;
89                 else if (t > ap->max)
90                         ap->max = t;
91                 ap->total += t;
92         }
93 }
94
95 static inline void avg_update_n(struct avg_info *ap, __u64 t, int n)
96 {
97         if (ap->n == 0) {
98                 ap->min = ap->max = t;
99                 ap->total = (n * t);
100         }
101         else {
102                 if (t < ap->min)
103                         ap->min = t;
104                 else if (t > ap->max)
105                         ap->max = t;
106                 ap->total += (n * t);
107         }
108
109         ap->n += n;
110 }
111
112 static inline void avg_unupdate(struct avg_info *ap, __u64 t)
113 {
114         ap->n--;
115         ap->total -= t;
116 }
117
118 static inline void update_lq(__u64 *last_q, struct avg_info *avg, __u64 time)
119 {
120         if (*last_q != ((__u64)-1))
121                 avg_update(avg, (time > *last_q) ? time - *last_q : 1);
122         *last_q = time;
123 }
124
125 static inline void dip_update_q(struct d_info *dip, struct io *iop)
126 {
127         if (remapper_dev(dip->device))
128                 update_lq(&dip->last_q, &dip->avgs.q2q_dm, iop->t.time);
129         else
130                 update_lq(&dip->last_q, &dip->avgs.q2q, iop->t.time);
131         update_qregion(&dip->regions, iop->t.time);
132 }
133
134 static inline struct io *io_alloc(void)
135 {
136         struct io *iop = malloc(sizeof(*iop));
137
138         memset(iop, 0, sizeof(struct io));
139         list_add_tail(&iop->a_head, &all_ios);
140
141         return iop;
142 }
143
144 static inline void io_free(struct io *iop)
145 {
146         list_del(&iop->a_head);
147         free(iop);
148 }
149
150 static inline void io_free_all(void)
151 {
152         struct io *iop;
153         struct list_head *p, *q;
154
155         list_for_each_safe(p, q, &all_ios) {
156                 iop = list_entry(p, struct io, a_head);
157                 free(iop);
158         }
159 }
160
161 static inline int io_setup(struct io *iop, enum iop_type type)
162 {
163         iop->type = type;
164         iop->dip = dip_add(iop->t.device, iop);
165         if (iop->linked) {
166                 iop->pip = find_process(iop->t.pid, NULL);
167                 iop->bytes_left = iop->t.bytes;
168         }
169
170         return iop->linked;
171 }
172
173 static inline void io_release(struct io *iop)
174 {
175         if (iop->linked)
176                 dip_rem(iop);
177         if (iop->pdu)
178                 free(iop->pdu);
179
180         io_free(iop);
181 }
182
183 #define UPDATE_AVGS(_avg, _iop, _pip, _time) do {                       \
184                 avg_update(&all_avgs. _avg , _time);                    \
185                 avg_update(&_iop->dip->avgs. _avg , _time);             \
186                 if (_pip) avg_update(&_pip->avgs. _avg , _time);        \
187         } while (0)
188
189 #define UPDATE_AVGS_N(_avg, _iop, _pip, _time, _n) do {                 \
190                 avg_update_n(&all_avgs. _avg , _time, _n);              \
191                 avg_update_n(&_iop->dip->avgs. _avg , _time, _n);       \
192                 if (_pip) avg_update_n(&_pip->avgs. _avg , _time,_n);   \
193         } while (0)
194
195 #define UNUPDATE_AVGS(_avg, _iop, _pip, _time) do {                     \
196                 avg_unupdate(&all_avgs. _avg , _time);                  \
197                 avg_unupdate(&_iop->dip->avgs. _avg , _time);           \
198                 if (_pip) avg_unupdate(&_pip->avgs. _avg , _time);      \
199         } while (0)
200
201 static inline void update_q2c(struct io *iop, __u64 c_time)
202 {
203         if (remapper_dev(iop->dip->device))
204                 UPDATE_AVGS(q2c_dm, iop, iop->pip, c_time);
205         else
206                 UPDATE_AVGS(q2c, iop, iop->pip, c_time);
207 }
208
209 static inline void update_q2a(struct io *iop, __u64 a_time)
210 {
211         if (remapper_dev(iop->dip->device))
212                 UPDATE_AVGS(q2a_dm, iop, iop->pip, a_time);
213         else
214                 UPDATE_AVGS(q2a, iop, iop->pip, a_time);
215 }
216
217 static inline void update_q2g(struct io *iop, __u64 g_time)
218 {
219         UPDATE_AVGS(q2g, iop, iop->pip, g_time);
220 }
221
222 static inline void update_s2g(struct io *iop, __u64 g_time)
223 {
224         UPDATE_AVGS(s2g, iop, iop->pip, g_time);
225 }
226
227 static inline void unupdate_q2g(struct io *iop, __u64 g_time)
228 {
229         UNUPDATE_AVGS(q2g, iop, iop->pip, g_time);
230 }
231
232 static inline void update_g2i(struct io *iop, __u64 i_time)
233 {
234         UPDATE_AVGS(g2i, iop, iop->pip, i_time);
235 }
236
237 static inline void unupdate_g2i(struct io *iop, __u64 i_time)
238 {
239         UNUPDATE_AVGS(g2i, iop, iop->pip, i_time);
240 }
241
242 static inline void update_q2m(struct io *iop, __u64 m_time)
243 {
244         UPDATE_AVGS(q2m, iop, iop->pip, m_time);
245 }
246
247 static inline void unupdate_q2m(struct io *iop, __u64 m_time)
248 {
249         UNUPDATE_AVGS(q2m, iop, iop->pip, m_time);
250 }
251
252 static inline void update_i2d(struct io *iop, __u64 d_time)
253 {
254         UPDATE_AVGS(i2d, iop, iop->pip, d_time);
255 }
256
257 static inline void unupdate_i2d(struct io *iop, __u64 d_time)
258 {
259         UNUPDATE_AVGS(i2d, iop, iop->pip, d_time);
260 }
261
262 static inline void update_m2d(struct io *iop, __u64 d_time)
263 {
264         UPDATE_AVGS(m2d, iop, iop->pip, d_time);
265 }
266
267 static inline void unupdate_m2d(struct io *iop, __u64 d_time)
268 {
269         UNUPDATE_AVGS(m2d, iop, iop->pip, d_time);
270 }
271
272 static inline void update_d2c(struct io *iop, __u64 c_time)
273 {
274         UPDATE_AVGS(d2c, iop, iop->pip, c_time);
275 }
276
277 static inline void update_blks(struct io *iop)
278 {
279         __u64 nblks = iop->t.bytes >> 9;
280         avg_update(&all_avgs.blks, nblks);
281         avg_update(&iop->dip->avgs.blks, nblks);
282         if (iop->pip)
283                 avg_update(&iop->pip->avgs.blks, nblks);
284 }
285
286 static inline struct rb_root *__get_root(struct d_info *dip, enum iop_type type)
287 {
288         struct rb_root *roots = dip->heads;
289         return &roots[type];
290 }
291
292 static inline int dip_rb_ins(struct d_info *dip, struct io *iop)
293 {
294         return rb_insert(__get_root(dip, iop->type), iop);
295 }
296
297 static inline void dip_rb_rem(struct io *iop)
298 {
299         rb_erase(&iop->rb_node, __get_root(iop->dip, iop->type));
300 }
301
302 static inline void dip_rb_fe(struct d_info *dip, enum iop_type type,
303                              struct io *iop,
304                              void (*fnc)(struct io *iop, struct io *this),
305                              struct list_head *head)
306 {
307         rb_foreach(__get_root(dip, type)->rb_node, iop, fnc, head);
308 }
309
310 static inline struct io *dip_rb_find_sec(struct d_info *dip,
311                                          enum iop_type type, __u64 sec)
312 {
313         return rb_find_sec(__get_root(dip, type), sec);
314 }
315
316 static inline __u64 tdelta(__u64 from, __u64 to)
317 {
318         return (from < to) ? (to - from) : 1;
319 }
320
321 static inline int type2c(enum iop_type type)
322 {
323         int c;
324
325         switch (type) {
326         case IOP_Q: c = 'Q'; break;
327         case IOP_X: c = 'X'; break;
328         case IOP_A: c = 'A'; break;
329         case IOP_I: c = 'I'; break;
330         case IOP_M: c = 'M'; break;
331         case IOP_D: c = 'D'; break;
332         case IOP_C: c = 'C'; break;
333         case IOP_R: c = 'R'; break;
334         case IOP_G: c = 'G'; break;
335         default   : c = '?'; break;
336         }
337
338         return c;
339 }
340
341 static inline int histo_idx(__u64 nbytes)
342 {
343         int idx = (nbytes >> 9) - 1;
344         return min(idx, N_HIST_BKTS-1);
345 }
346
347 static inline void update_q_histo(__u64 nbytes)
348 {
349         q_histo[histo_idx(nbytes)]++;
350 }
351
352 static inline void update_d_histo(__u64 nbytes)
353 {
354         d_histo[histo_idx(nbytes)]++;
355 }
356
357 static inline struct io *io_first_list(struct list_head *head)
358 {
359         if (list_empty(head))
360                 return NULL;
361
362         return list_entry(head->next, struct io, f_head);
363 }
364
365 static inline void __dump_iop(FILE *ofp, struct io *iop, int extra_nl)
366 {
367         fprintf(ofp, "%5d.%09lu %3d,%-3d %c %10llu+%-4u\n",
368                 (int)SECONDS(iop->t.time),
369                 (unsigned long)NANO_SECONDS(iop->t.time),
370                 MAJOR(iop->t.device), MINOR(iop->t.device), type2c(iop->type),
371                 (unsigned long long)iop->t.sector, t_sec(&iop->t));
372         if (extra_nl) fprintf(ofp, "\n");
373 }
374
375 static inline void __dump_iop2(FILE *ofp, struct io *a_iop, struct io *l_iop)
376 {
377         fprintf(ofp, "%5d.%09lu %3d,%-3d %c %10llu+%-4u <- (%3d,%-3d) %10llu\n",
378                 (int)SECONDS(a_iop->t.time),
379                 (unsigned long)NANO_SECONDS(a_iop->t.time),
380                 MAJOR(a_iop->t.device), MINOR(a_iop->t.device),
381                 type2c(a_iop->type), (unsigned long long)a_iop->t.sector,
382                 t_sec(&a_iop->t), MAJOR(l_iop->t.device),
383                 MINOR(l_iop->t.device), (unsigned long long)l_iop->t.sector);
384 }