Commit | Line | Data |
---|---|---|
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 | */ | |
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)) | |
5225e788 | 34 | #define IOP_READ(iop) ((iop)->t.action & BLK_TC_ACT(BLK_TC_READ)) |
21e47d90 | 35 | #define IOP_RW(iop) (IOP_READ(iop) ? 1 : 0) |
63eba147 JA |
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 | ||
21e47d90 ADB |
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 | ||
63eba147 JA |
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; | |
5225e788 | 159 | void *seek_handle; |
21e47d90 | 160 | struct stats stats, all_stats; |
63eba147 JA |
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; | |
97d13fb0 AB |
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; | |
63eba147 | 197 | struct { struct io *x_q; } x; |
63eba147 JA |
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; | |
21e47d90 | 207 | extern char *seek_name, *iostat_name; |
63eba147 | 208 | extern double range_delta; |
21e47d90 | 209 | extern FILE *ranges_ofp, *avgs_ofp, *iostat_ofp; |
63eba147 JA |
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; | |
21e47d90 | 220 | extern __u64 iostat_interval, iostat_last_stamp; |
63eba147 JA |
221 | |
222 | void add_trace(struct io *iop); | |
223 | int in_devices(struct blk_io_trace *t); | |
21e47d90 | 224 | char *make_dev_hdr(char *pad, size_t len, struct d_info *dip); |
63eba147 JA |
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); | |
5225e788 AB |
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); | |
63eba147 | 248 | |
21e47d90 ADB |
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 | ||
63eba147 | 257 | #include "inlines.h" |