Merge branch 'master' of ssh://git.kernel.dk/data/git/blktrace
[blktrace.git] / btt / inlines.h
CommitLineData
63eba147
JA
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 */
63eba147 21
e71e4b78 22static inline struct range_info *new_cur(__u64 time)
63eba147 23{
6eb42155 24 struct range_info *cur = malloc(sizeof(struct range_info));
63eba147
JA
25
26 INIT_LIST_HEAD(&cur->head);
27 cur->start = time;
28 return cur;
29}
30
6eb42155
ADB
31static inline void update_range(struct list_head *head_p,
32 struct range_info **cur_p, __u64 time)
63eba147
JA
33{
34 if (*cur_p == NULL)
35 *cur_p = new_cur(time);
36 else {
095181f2 37 __u64 my_delta = (time > (*cur_p)->end) ? time - (*cur_p)->end : 1;
63eba147
JA
38 if (BIT_TIME(my_delta) >= range_delta) {
39 list_add_tail(&(*cur_p)->head, head_p);
40 *cur_p = new_cur(time);
41 }
42 }
43
44 (*cur_p)->end = time;
45}
46
e71e4b78 47static inline void init_region(struct region_info *reg)
63eba147
JA
48{
49 INIT_LIST_HEAD(&reg->qranges);
50 INIT_LIST_HEAD(&reg->cranges);
51 reg->qr_cur = reg->cr_cur = NULL;
52}
53
e71e4b78 54static inline void update_qregion(struct region_info *reg, __u64 time)
63eba147
JA
55{
56 update_range(&reg->qranges, &reg->qr_cur, time);
57}
58
e71e4b78 59static inline void update_cregion(struct region_info *reg, __u64 time)
63eba147
JA
60{
61 update_range(&reg->cranges, &reg->cr_cur, time);
62}
63
e71e4b78 64static inline void avg_update(struct avg_info *ap, __u64 t)
63eba147
JA
65{
66 if (ap->n++ == 0)
67 ap->min = ap->total = ap->max = t;
68 else {
69 if (t < ap->min)
70 ap->min = t;
71 else if (t > ap->max)
72 ap->max = t;
73 ap->total += t;
74 }
75}
76
d76c5b81
AB
77static inline void avg_update_n(struct avg_info *ap, __u64 t, int n)
78{
79 if (ap->n == 0) {
80 ap->min = ap->max = t;
81 ap->total = (n * t);
82 }
83 else {
84 if (t < ap->min)
85 ap->min = t;
86 else if (t > ap->max)
87 ap->max = t;
88 ap->total += (n * t);
89 }
90
91 ap->n += n;
92}
93
6eb42155
ADB
94static inline void avg_unupdate(struct avg_info *ap, __u64 t)
95{
96 ap->n--;
97 ap->total -= t;
98}
99
e71e4b78 100static inline void update_lq(__u64 *last_q, struct avg_info *avg, __u64 time)
63eba147
JA
101{
102 if (*last_q != ((__u64)-1))
095181f2 103 avg_update(avg, (time > *last_q) ? time - *last_q : 1);
63eba147
JA
104 *last_q = time;
105}
106
e71e4b78 107static inline void dip_update_q(struct d_info *dip, struct io *iop)
63eba147
JA
108{
109 update_lq(&dip->last_q, &dip->avgs.q2q, iop->t.time);
110 update_qregion(&dip->regions, iop->t.time);
111}
112
6eb42155 113static inline struct io *io_alloc(void)
63eba147 114{
6eb42155 115 struct io *iop;
63eba147 116
6eb42155
ADB
117 if (!list_empty(&free_ios)) {
118 iop = list_entry(free_ios.next, struct io, f_head);
119 LIST_DEL(&iop->f_head);
120 }
63eba147 121 else
6eb42155 122 iop = malloc(sizeof(struct io));
63eba147 123
095181f2 124 memset(iop, 0, sizeof(struct io));
d76c5b81
AB
125 INIT_LIST_HEAD(&iop->down_list);
126 INIT_LIST_HEAD(&iop->up_list);
127
128#if defined(DEBUG)
129 iop->f_head.next = LIST_POISON1;
130 iop->c_pending.next = LIST_POISON1;
131 iop->retry.next = LIST_POISON1;
132#endif
095181f2
JA
133
134 return iop;
63eba147
JA
135}
136
6eb42155 137static inline void io_free(struct io *iop)
63eba147 138{
095181f2
JA
139# if defined(DEBUG)
140 memset(iop, 0, sizeof(*iop));
141# endif
6eb42155 142 list_add_tail(&iop->f_head, &free_ios);
63eba147
JA
143}
144
095181f2 145static inline int io_setup(struct io *iop, enum iop_type type)
63eba147
JA
146{
147 iop->type = type;
095181f2
JA
148 iop->dip = dip_add(iop->t.device, iop);
149 if (iop->linked) {
150 iop->pip = find_process(iop->t.pid, NULL);
095181f2
JA
151 iop->bytes_left = iop->t.bytes;
152 }
153
154 return iop->linked;
63eba147
JA
155}
156
6eb42155 157static inline void io_release(struct io *iop)
63eba147 158{
d76c5b81
AB
159 ASSERT(iop->f_head.next == LIST_POISON1);
160 ASSERT(iop->c_pending.next == LIST_POISON1);
161 ASSERT(iop->retry.next == LIST_POISON1);
162 ASSERT(list_empty(&iop->up_list));
163 ASSERT(list_empty(&iop->down_list));
164
095181f2 165 if (iop->linked)
6eb42155 166 dip_rem(iop);
6eb42155
ADB
167 if (iop->pdu)
168 free(iop->pdu);
d76c5b81 169
6eb42155 170 io_free(iop);
63eba147
JA
171}
172
173#define UPDATE_AVGS(_avg, _iop, _pip, _time) do { \
174 avg_update(&all_avgs. _avg , _time); \
175 avg_update(&_iop->dip->avgs. _avg , _time); \
176 if (_pip) avg_update(&_pip->avgs. _avg , _time); \
177 } while (0)
178
d76c5b81
AB
179#define UPDATE_AVGS_N(_avg, _iop, _pip, _time, _n) do { \
180 avg_update_n(&all_avgs. _avg , _time, _n); \
181 avg_update_n(&_iop->dip->avgs. _avg , _time, _n); \
182 if (_pip) avg_update_n(&_pip->avgs. _avg , _time,_n); \
183 } while (0)
184
6eb42155
ADB
185#define UNUPDATE_AVGS(_avg, _iop, _pip, _time) do { \
186 avg_unupdate(&all_avgs. _avg , _time); \
187 avg_unupdate(&_iop->dip->avgs. _avg , _time); \
188 if (_pip) avg_unupdate(&_pip->avgs. _avg , _time); \
189 } while (0)
190
e71e4b78 191static inline void update_q2c(struct io *iop, __u64 c_time)
63eba147 192{
d76c5b81
AB
193#if defined(DEBUG)
194 if (per_io_ofp) fprintf(per_io_ofp, "q2c %13.9f\n", BIT_TIME(c_time));
195#endif
63eba147
JA
196 UPDATE_AVGS(q2c, iop, iop->pip, c_time);
197}
198
e71e4b78 199static inline void update_q2a(struct io *iop, __u64 a_time)
63eba147 200{
d76c5b81
AB
201#if defined(DEBUG)
202 if (per_io_ofp) fprintf(per_io_ofp, "q2a %13.9f\n", BIT_TIME(a_time));
203#endif
63eba147
JA
204 UPDATE_AVGS(q2a, iop, iop->pip, a_time);
205}
206
e71e4b78 207static inline void update_q2i(struct io *iop, __u64 i_time)
63eba147 208{
d76c5b81
AB
209#if defined(DEBUG)
210 if (per_io_ofp) fprintf(per_io_ofp, "q2i %13.9f\n", BIT_TIME(i_time));
211#endif
63eba147
JA
212 UPDATE_AVGS(q2i, iop, iop->pip, i_time);
213}
214
d76c5b81
AB
215static inline void unupdate_q2i(struct io *iop, __u64 i_time)
216{
217 UNUPDATE_AVGS(q2i, iop, iop->pip, i_time);
218}
219
e71e4b78 220static inline void update_i2d(struct io *iop, __u64 d_time)
63eba147 221{
d76c5b81
AB
222#if defined(DEBUG)
223 if (per_io_ofp) fprintf(per_io_ofp, "i2d %13.9f\n", BIT_TIME(d_time));
224#endif
63eba147
JA
225 UPDATE_AVGS(i2d, iop, iop->pip, d_time);
226}
227
6eb42155
ADB
228static inline void unupdate_i2d(struct io *iop, __u64 d_time)
229{
230 UNUPDATE_AVGS(i2d, iop, iop->pip, d_time);
231}
232
d76c5b81 233static inline void update_d2c(struct io *iop, int n, __u64 c_time)
63eba147 234{
d76c5b81
AB
235 if (per_io_ofp) fprintf(per_io_ofp, "d2c %13.9f\n", n*BIT_TIME(c_time));
236 UPDATE_AVGS_N(d2c, iop, iop->pip, c_time, n);
63eba147
JA
237}
238
e71e4b78 239static inline void update_blks(struct io *iop)
63eba147
JA
240{
241 __u64 nblks = iop->t.bytes >> 9;
242 avg_update(&all_avgs.blks, nblks);
6eb42155 243 ASSERT(iop->dip != NULL);
63eba147
JA
244 avg_update(&iop->dip->avgs.blks, nblks);
245 if (iop->pip)
246 avg_update(&iop->pip->avgs.blks, nblks);
247}
6eb42155
ADB
248
249static inline struct rb_root *__get_root(struct d_info *dip, enum iop_type type)
250{
251 struct rb_root *roots = dip->heads;
252 return &roots[type];
253}
254
255static inline void *dip_rb_mkhds(void)
256{
257 size_t len = N_IOP_TYPES * sizeof(struct rb_root);
258 return memset(malloc(len), 0, len);
259}
260
095181f2 261static inline int dip_rb_ins(struct d_info *dip, struct io *iop)
6eb42155 262{
095181f2 263 return rb_insert(__get_root(dip, iop->type), iop);
6eb42155
ADB
264}
265
266static inline void dip_rb_rem(struct io *iop)
267{
268 rb_erase(&iop->rb_node, __get_root(iop->dip, iop->type));
d76c5b81
AB
269#if defined(DEBUG)
270 rb_tree_size--;
271#endif
6eb42155
ADB
272}
273
274static inline void dip_rb_fe(struct d_info *dip, enum iop_type type,
275 struct io *iop,
276 void (*fnc)(struct io *iop, struct io *this),
277 struct list_head *head)
278{
279 rb_foreach(__get_root(dip, type)->rb_node, iop, fnc, head);
280}
281
282static inline struct io *dip_rb_find_sec(struct d_info *dip,
283 enum iop_type type, __u64 sec)
284{
285 return rb_find_sec(__get_root(dip, type), sec);
286}
095181f2 287
d76c5b81 288static inline void bump_retry(__u64 now)
095181f2 289{
d76c5b81
AB
290 if (!list_empty(&retries))
291 next_retry_check = now + (100 * 1000); // 100 usec
292 else
293 next_retry_check = 0;
095181f2
JA
294}
295
296static inline void add_retry(struct io *iop)
297{
d76c5b81 298 bump_retry(iop->t.time);
001b2633
JA
299 if (!iop->on_retry_list) {
300 list_add_tail(&iop->retry, &retries);
301 iop->on_retry_list = 1;
302 }
095181f2
JA
303}
304
305static inline void del_retry(struct io *iop)
306{
001b2633
JA
307 if (iop->on_retry_list) {
308 LIST_DEL(&iop->retry);
309 iop->on_retry_list = 0;
310 }
d76c5b81 311 bump_retry(iop->t.time);
095181f2
JA
312}
313
314static inline __u64 tdelta(struct io *iop1, struct io *iop2)
315{
316 __u64 t1 = iop1->t.time;
317 __u64 t2 = iop2->t.time;
318 return (t1 < t2) ? (t2 - t1) : 1;
319}
d76c5b81
AB
320
321static inline int remapper_dev(__u32 dev)
322{
323 int mjr = MAJOR(dev);
324 return mjr == 9 || mjr == 254; // 253? That's what is in blkparse.c
325 // But I see 254...
326}
327
328static inline void dump_iop(struct io *iop, int extra_nl)
329{
330 if (per_io_ofp)
331 __dump_iop(per_io_ofp, iop, extra_nl);
332}
333
334static inline void dump_iop2(struct io *a_iop, struct io *l_iop)
335{
336 if (per_io_ofp)
337 __dump_iop2(per_io_ofp, a_iop, l_iop);
338}
339
340static inline int type2c(enum iop_type type)
341{
342 int c;
343
344 switch (type) {
345 case IOP_Q: c = 'Q'; break;
346 case IOP_X: c = 'X'; break;
347 case IOP_A: c = 'A'; break;
348 case IOP_I: c = 'I'; break;
349 case IOP_M: c = 'M'; break;
350 case IOP_D: c = 'D'; break;
351 case IOP_C: c = 'C'; break;
352 case IOP_R: c = 'R'; break;
353 case IOP_L: c = 'L'; break;
354 default : c = '?'; break;
355 }
356
357 return c;
358}
359
360static inline void bilink_free(struct bilink *blp)
361{
362 free(blp);
363}
364
365static inline struct bilink *bilink_alloc(struct io *diop, struct io *uiop)
366{
367 struct bilink *blp = malloc(sizeof(*blp));
368
369 blp->diop = diop;
370 blp->uiop = uiop;
371
372 return blp;
373}
374
375static inline void bilink(struct io *diop, struct io *uiop)
376{
377 struct bilink *blp = bilink_alloc(diop, uiop);
378
379 list_add_tail(&blp->down_head, &diop->up_list);
380 list_add_tail(&blp->up_head, &uiop->down_list);
381
382 diop->up_len++;
383 uiop->down_len++;
384}
385
386static inline void biunlink(struct bilink *blp)
387{
388 LIST_DEL(&blp->down_head);
389 LIST_DEL(&blp->up_head);
390 blp->diop->up_len--;
391 blp->uiop->down_len--;
392 bilink_free(blp);
393}
394
395static inline struct io *bilink_first_down(struct io *iop,
396 struct bilink **blp_p)
397{
398 struct bilink *blp;
399
400 if (list_empty(&iop->down_list))
401 return NULL;
402 blp = list_entry(iop->down_list.next, struct bilink, up_head);
403
404 if (blp_p != NULL)
405 *blp_p = blp;
406 return blp->diop;
407}
408
409static inline struct io *bilink_first_up(struct io *iop, struct bilink **blp_p)
410{
411 struct bilink *blp;
412
413 if (list_empty(&iop->up_list))
414 return NULL;
415 blp = list_entry(iop->up_list.next, struct bilink, down_head);
416
417 if (blp_p != NULL)
418 *blp_p = blp;
419 return blp->diop;
420}
421
422typedef void (*bilink_func)(struct io *diop, struct io *uiop, void *param);
423static inline void bilink_for_each_down(bilink_func func, struct io *uiop,
424 void *param, int ul)
425{
426 struct bilink *blp;
427 struct list_head *p, *q;
428
429 list_for_each_safe(p, q, &uiop->down_list) {
430 blp = list_entry(p, struct bilink, up_head);
431 func(blp->diop, uiop, param);
432 if (ul)
433 biunlink(blp);
434 }
435}