[PATCH] Add Alan's btt tool
[blktrace.git] / btt / traverse.c
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 "globals.h"
22
23 typedef struct io *iop_t;
24 typedef iop_t (*iop_func_t)(__u64 *, struct io*);
25
26 struct io *iop_q_func(__u64 *timeline, struct io *iop);
27 struct io *iop_x_func(__u64 *timeline, struct io *iop);
28 struct io *iop_a_func(__u64 *timeline, struct io *iop);
29 struct io *iop_m_func(__u64 *timeline, struct io *iop);
30 struct io *iop_i_func(__u64 *timeline, struct io *iop);
31 struct io *iop_d_func(__u64 *timeline, struct io *iop);
32 struct io *iop_c_func(__u64 *timeline, struct io *iop);
33 struct io *iop_y_func(__u64 *timeline, struct io *iop);
34
35 iop_func_t traverse_func[] = {
36         iop_q_func,
37         iop_x_func,
38         iop_a_func,
39         iop_m_func,
40         iop_i_func,
41         iop_d_func,
42         iop_c_func,
43         iop_y_func,
44 };
45
46 void __traverse(__u64 *timeline, struct io *iop)
47 {
48         while (iop != NULL && !iop->traversed) {
49                 iop->traversed++;
50                 iop = traverse_func[iop->type](timeline, iop);
51         }
52 }
53
54 void traverse(struct io *iop)
55 {
56         int i;
57         __u64 timeline[N_IOP_TYPES];
58
59         for (i = 0; i < N_IOP_TYPES; i++)
60                 timeline[i] = 0.0;
61
62         __traverse(timeline, iop);
63 }
64
65 void iop_q_update(__u64 *timeline, struct io *iop, __u64 q_time)
66 {
67         update_q2c(iop, timeline[IOP_C] - q_time);
68
69         if (timeline[IOP_A] > 0.0)      // IOP_X too
70                 update_q2a(iop, timeline[IOP_A] - q_time);
71         else                            //IOP_M too
72                 update_q2i(iop, timeline[IOP_I] - q_time);
73
74         update_i2d(iop, timeline[IOP_D] - timeline[IOP_I]);
75         update_d2c(iop, timeline[IOP_C] - timeline[IOP_D]);
76 }
77
78 struct io *iop_q_func(__u64 *timeline, struct io *iop)
79 {
80         timeline[IOP_Q] = iop->t.time;
81         iop_q_update(timeline, iop, iop->t.time);
82
83         if (iop->u.q.qp_type == Q_A)
84                 return iop->u.q.qp.q_a;
85         else if (iop->u.q.qp_type == Q_X)
86                 return iop->u.q.qp.q_x;
87
88         /* Q_NONE */
89         return NULL;
90 }
91
92 struct io *iop_x_func(__u64 *timeline, struct io *iop)
93 {
94         timeline[IOP_A] = iop->t.time;  // Cover X & A in one slice
95         return iop->u.x.x_q;
96 }
97
98 struct io *iop_a_func(__u64 *timeline, struct io *iop)
99 {
100         timeline[IOP_A] = iop->t.time;
101         return iop->u.a.a_q;
102 }
103
104 struct io *iop_m_func(__u64 *timeline, struct io *iop)
105 {
106         timeline[IOP_I] = iop->t.time;  // Cover M & I in one slice
107         return iop->u.m.m_q;
108 }
109
110 struct io *iop_i_func(__u64 *timeline, struct io *iop)
111 {
112         struct list_head *p;
113         struct io_list *iolp;
114
115         timeline[IOP_I] = iop->t.time;
116         __list_for_each(p, &iop->u.i.i_qs_head) {
117                 iolp = list_entry(p, struct io_list, head);
118                 __traverse(timeline, iolp->iop);
119         }
120
121         return NULL;
122 }
123
124 struct io *iop_d_func(__u64 *timeline, struct io *iop)
125 {
126         struct list_head *p;
127         struct io_list *iolp;
128
129         timeline[IOP_D] = iop->t.time;
130         __list_for_each(p, &iop->u.d.d_im_head) {
131                 iolp = list_entry(p, struct io_list, head);
132                 __traverse(timeline, iolp->iop);
133         }
134
135         return NULL;
136 }
137
138 struct io *iop_c_func(__u64 *timeline, struct io *iop)
139 {
140         timeline[IOP_C] = iop->t.time;
141         return iop->u.c.c_d;
142 }
143
144 struct io *iop_y_func(__u64 *timeline, struct io *iop)
145 {
146         timeline[IOP_Y] = iop->t.time;
147         __traverse(timeline, iop->u.y.y_c1);
148         __traverse(timeline, iop->u.y.y_c2);
149         return NULL;
150 }