1*1a3d31e3SAndroid Build Coastguard Worker /*
2*1a3d31e3SAndroid Build Coastguard Worker * This file contains format parsing code for blkparse, allowing you to
3*1a3d31e3SAndroid Build Coastguard Worker * customize the individual action format and generel output format.
4*1a3d31e3SAndroid Build Coastguard Worker */
5*1a3d31e3SAndroid Build Coastguard Worker #include <stdio.h>
6*1a3d31e3SAndroid Build Coastguard Worker #include <string.h>
7*1a3d31e3SAndroid Build Coastguard Worker #include <stdlib.h>
8*1a3d31e3SAndroid Build Coastguard Worker #include <unistd.h>
9*1a3d31e3SAndroid Build Coastguard Worker #include <ctype.h>
10*1a3d31e3SAndroid Build Coastguard Worker #include <time.h>
11*1a3d31e3SAndroid Build Coastguard Worker
12*1a3d31e3SAndroid Build Coastguard Worker #include "blktrace.h"
13*1a3d31e3SAndroid Build Coastguard Worker
14*1a3d31e3SAndroid Build Coastguard Worker #define VALID_SPECS "ABCDFGIMPQRSTUWX"
15*1a3d31e3SAndroid Build Coastguard Worker
16*1a3d31e3SAndroid Build Coastguard Worker #define HEADER "%D %2c %8s %5T.%9t %5p %2a %3d "
17*1a3d31e3SAndroid Build Coastguard Worker
18*1a3d31e3SAndroid Build Coastguard Worker static char *override_format[256];
19*1a3d31e3SAndroid Build Coastguard Worker
valid_spec(int spec)20*1a3d31e3SAndroid Build Coastguard Worker static inline int valid_spec(int spec)
21*1a3d31e3SAndroid Build Coastguard Worker {
22*1a3d31e3SAndroid Build Coastguard Worker return strchr(VALID_SPECS, spec) != NULL;
23*1a3d31e3SAndroid Build Coastguard Worker }
24*1a3d31e3SAndroid Build Coastguard Worker
set_all_format_specs(char * option)25*1a3d31e3SAndroid Build Coastguard Worker void set_all_format_specs(char *option)
26*1a3d31e3SAndroid Build Coastguard Worker {
27*1a3d31e3SAndroid Build Coastguard Worker char *p;
28*1a3d31e3SAndroid Build Coastguard Worker
29*1a3d31e3SAndroid Build Coastguard Worker for (p = VALID_SPECS; *p; p++)
30*1a3d31e3SAndroid Build Coastguard Worker if (override_format[(int)(*p)] == NULL)
31*1a3d31e3SAndroid Build Coastguard Worker override_format[(int)(*p)] = strdup(option);
32*1a3d31e3SAndroid Build Coastguard Worker }
33*1a3d31e3SAndroid Build Coastguard Worker
add_format_spec(char * option)34*1a3d31e3SAndroid Build Coastguard Worker int add_format_spec(char *option)
35*1a3d31e3SAndroid Build Coastguard Worker {
36*1a3d31e3SAndroid Build Coastguard Worker int spec = optarg[0];
37*1a3d31e3SAndroid Build Coastguard Worker
38*1a3d31e3SAndroid Build Coastguard Worker if (!valid_spec(spec)) {
39*1a3d31e3SAndroid Build Coastguard Worker fprintf(stderr,"Bad format specifier %c\n", spec);
40*1a3d31e3SAndroid Build Coastguard Worker return 1;
41*1a3d31e3SAndroid Build Coastguard Worker }
42*1a3d31e3SAndroid Build Coastguard Worker if (optarg[1] != ',') {
43*1a3d31e3SAndroid Build Coastguard Worker fprintf(stderr,"Bad format specifier - need ',' %s\n", option);
44*1a3d31e3SAndroid Build Coastguard Worker return 1;
45*1a3d31e3SAndroid Build Coastguard Worker }
46*1a3d31e3SAndroid Build Coastguard Worker option += 2;
47*1a3d31e3SAndroid Build Coastguard Worker
48*1a3d31e3SAndroid Build Coastguard Worker override_format[spec] = strdup(option);
49*1a3d31e3SAndroid Build Coastguard Worker
50*1a3d31e3SAndroid Build Coastguard Worker return 0;
51*1a3d31e3SAndroid Build Coastguard Worker }
52*1a3d31e3SAndroid Build Coastguard Worker
fill_rwbs(char * rwbs,struct blk_io_trace * t)53*1a3d31e3SAndroid Build Coastguard Worker static inline void fill_rwbs(char *rwbs, struct blk_io_trace *t)
54*1a3d31e3SAndroid Build Coastguard Worker {
55*1a3d31e3SAndroid Build Coastguard Worker int w = t->action & BLK_TC_ACT(BLK_TC_WRITE);
56*1a3d31e3SAndroid Build Coastguard Worker int a = t->action & BLK_TC_ACT(BLK_TC_AHEAD);
57*1a3d31e3SAndroid Build Coastguard Worker int s = t->action & BLK_TC_ACT(BLK_TC_SYNC);
58*1a3d31e3SAndroid Build Coastguard Worker int m = t->action & BLK_TC_ACT(BLK_TC_META);
59*1a3d31e3SAndroid Build Coastguard Worker int d = t->action & BLK_TC_ACT(BLK_TC_DISCARD);
60*1a3d31e3SAndroid Build Coastguard Worker int f = t->action & BLK_TC_ACT(BLK_TC_FLUSH);
61*1a3d31e3SAndroid Build Coastguard Worker int u = t->action & BLK_TC_ACT(BLK_TC_FUA);
62*1a3d31e3SAndroid Build Coastguard Worker int i = 0;
63*1a3d31e3SAndroid Build Coastguard Worker
64*1a3d31e3SAndroid Build Coastguard Worker if (f)
65*1a3d31e3SAndroid Build Coastguard Worker rwbs[i++] = 'F'; /* flush */
66*1a3d31e3SAndroid Build Coastguard Worker
67*1a3d31e3SAndroid Build Coastguard Worker if (d)
68*1a3d31e3SAndroid Build Coastguard Worker rwbs[i++] = 'D';
69*1a3d31e3SAndroid Build Coastguard Worker else if (w)
70*1a3d31e3SAndroid Build Coastguard Worker rwbs[i++] = 'W';
71*1a3d31e3SAndroid Build Coastguard Worker else if (t->bytes)
72*1a3d31e3SAndroid Build Coastguard Worker rwbs[i++] = 'R';
73*1a3d31e3SAndroid Build Coastguard Worker else
74*1a3d31e3SAndroid Build Coastguard Worker rwbs[i++] = 'N';
75*1a3d31e3SAndroid Build Coastguard Worker
76*1a3d31e3SAndroid Build Coastguard Worker if (u)
77*1a3d31e3SAndroid Build Coastguard Worker rwbs[i++] = 'F'; /* fua */
78*1a3d31e3SAndroid Build Coastguard Worker if (a)
79*1a3d31e3SAndroid Build Coastguard Worker rwbs[i++] = 'A';
80*1a3d31e3SAndroid Build Coastguard Worker if (s)
81*1a3d31e3SAndroid Build Coastguard Worker rwbs[i++] = 'S';
82*1a3d31e3SAndroid Build Coastguard Worker if (m)
83*1a3d31e3SAndroid Build Coastguard Worker rwbs[i++] = 'M';
84*1a3d31e3SAndroid Build Coastguard Worker
85*1a3d31e3SAndroid Build Coastguard Worker rwbs[i] = '\0';
86*1a3d31e3SAndroid Build Coastguard Worker }
87*1a3d31e3SAndroid Build Coastguard Worker
88*1a3d31e3SAndroid Build Coastguard Worker static const char *
print_time(unsigned long long timestamp)89*1a3d31e3SAndroid Build Coastguard Worker print_time(unsigned long long timestamp)
90*1a3d31e3SAndroid Build Coastguard Worker {
91*1a3d31e3SAndroid Build Coastguard Worker static char timebuf[128];
92*1a3d31e3SAndroid Build Coastguard Worker struct tm *tm;
93*1a3d31e3SAndroid Build Coastguard Worker time_t sec;
94*1a3d31e3SAndroid Build Coastguard Worker unsigned long nsec;
95*1a3d31e3SAndroid Build Coastguard Worker
96*1a3d31e3SAndroid Build Coastguard Worker sec = abs_start_time.tv_sec + SECONDS(timestamp);
97*1a3d31e3SAndroid Build Coastguard Worker nsec = abs_start_time.tv_nsec + NANO_SECONDS(timestamp);
98*1a3d31e3SAndroid Build Coastguard Worker if (nsec >= 1000000000) {
99*1a3d31e3SAndroid Build Coastguard Worker nsec -= 1000000000;
100*1a3d31e3SAndroid Build Coastguard Worker sec += 1;
101*1a3d31e3SAndroid Build Coastguard Worker }
102*1a3d31e3SAndroid Build Coastguard Worker
103*1a3d31e3SAndroid Build Coastguard Worker tm = localtime(&sec);
104*1a3d31e3SAndroid Build Coastguard Worker snprintf(timebuf, sizeof(timebuf),
105*1a3d31e3SAndroid Build Coastguard Worker "%02u:%02u:%02u.%06lu",
106*1a3d31e3SAndroid Build Coastguard Worker tm->tm_hour,
107*1a3d31e3SAndroid Build Coastguard Worker tm->tm_min,
108*1a3d31e3SAndroid Build Coastguard Worker tm->tm_sec,
109*1a3d31e3SAndroid Build Coastguard Worker nsec / 1000);
110*1a3d31e3SAndroid Build Coastguard Worker return timebuf;
111*1a3d31e3SAndroid Build Coastguard Worker }
112*1a3d31e3SAndroid Build Coastguard Worker
pdu_rest_is_zero(unsigned char * pdu,int len)113*1a3d31e3SAndroid Build Coastguard Worker static inline int pdu_rest_is_zero(unsigned char *pdu, int len)
114*1a3d31e3SAndroid Build Coastguard Worker {
115*1a3d31e3SAndroid Build Coastguard Worker static char zero[4096];
116*1a3d31e3SAndroid Build Coastguard Worker
117*1a3d31e3SAndroid Build Coastguard Worker return !memcmp(pdu, zero, len);
118*1a3d31e3SAndroid Build Coastguard Worker }
119*1a3d31e3SAndroid Build Coastguard Worker
dump_pdu(unsigned char * pdu_buf,int pdu_len)120*1a3d31e3SAndroid Build Coastguard Worker static char *dump_pdu(unsigned char *pdu_buf, int pdu_len)
121*1a3d31e3SAndroid Build Coastguard Worker {
122*1a3d31e3SAndroid Build Coastguard Worker static char p[4096];
123*1a3d31e3SAndroid Build Coastguard Worker int i, len;
124*1a3d31e3SAndroid Build Coastguard Worker
125*1a3d31e3SAndroid Build Coastguard Worker if (!pdu_buf || !pdu_len)
126*1a3d31e3SAndroid Build Coastguard Worker return NULL;
127*1a3d31e3SAndroid Build Coastguard Worker
128*1a3d31e3SAndroid Build Coastguard Worker for (len = 0, i = 0; i < pdu_len; i++) {
129*1a3d31e3SAndroid Build Coastguard Worker if (i)
130*1a3d31e3SAndroid Build Coastguard Worker len += sprintf(p + len, " ");
131*1a3d31e3SAndroid Build Coastguard Worker
132*1a3d31e3SAndroid Build Coastguard Worker len += sprintf(p + len, "%02x", pdu_buf[i]);
133*1a3d31e3SAndroid Build Coastguard Worker
134*1a3d31e3SAndroid Build Coastguard Worker /*
135*1a3d31e3SAndroid Build Coastguard Worker * usually dump for cdb dumps where we can see lots of
136*1a3d31e3SAndroid Build Coastguard Worker * zeroes, stop when the rest is just zeroes and indicate
137*1a3d31e3SAndroid Build Coastguard Worker * so with a .. appended
138*1a3d31e3SAndroid Build Coastguard Worker */
139*1a3d31e3SAndroid Build Coastguard Worker if (!pdu_buf[i] && pdu_rest_is_zero(pdu_buf + i, pdu_len - i)) {
140*1a3d31e3SAndroid Build Coastguard Worker sprintf(p + len, " ..");
141*1a3d31e3SAndroid Build Coastguard Worker break;
142*1a3d31e3SAndroid Build Coastguard Worker }
143*1a3d31e3SAndroid Build Coastguard Worker }
144*1a3d31e3SAndroid Build Coastguard Worker
145*1a3d31e3SAndroid Build Coastguard Worker return p;
146*1a3d31e3SAndroid Build Coastguard Worker }
147*1a3d31e3SAndroid Build Coastguard Worker
148*1a3d31e3SAndroid Build Coastguard Worker #define pdu_start(t) (((void *) (t) + sizeof(struct blk_io_trace)))
149*1a3d31e3SAndroid Build Coastguard Worker
get_pdu_int(struct blk_io_trace * t)150*1a3d31e3SAndroid Build Coastguard Worker static unsigned int get_pdu_int(struct blk_io_trace *t)
151*1a3d31e3SAndroid Build Coastguard Worker {
152*1a3d31e3SAndroid Build Coastguard Worker __u64 *val = pdu_start(t);
153*1a3d31e3SAndroid Build Coastguard Worker
154*1a3d31e3SAndroid Build Coastguard Worker return be64_to_cpu(*val);
155*1a3d31e3SAndroid Build Coastguard Worker }
156*1a3d31e3SAndroid Build Coastguard Worker
get_pdu_remap(struct blk_io_trace * t,struct blk_io_trace_remap * r)157*1a3d31e3SAndroid Build Coastguard Worker static void get_pdu_remap(struct blk_io_trace *t, struct blk_io_trace_remap *r)
158*1a3d31e3SAndroid Build Coastguard Worker {
159*1a3d31e3SAndroid Build Coastguard Worker struct blk_io_trace_remap *__r = pdu_start(t);
160*1a3d31e3SAndroid Build Coastguard Worker __u64 sector_from = __r->sector_from;
161*1a3d31e3SAndroid Build Coastguard Worker
162*1a3d31e3SAndroid Build Coastguard Worker r->device_from = be32_to_cpu(__r->device_from);
163*1a3d31e3SAndroid Build Coastguard Worker r->device_to = be32_to_cpu(__r->device_to);
164*1a3d31e3SAndroid Build Coastguard Worker r->sector_from = be64_to_cpu(sector_from);
165*1a3d31e3SAndroid Build Coastguard Worker }
166*1a3d31e3SAndroid Build Coastguard Worker
print_field(char * act,struct per_cpu_info * pci,struct blk_io_trace * t,unsigned long long elapsed,int pdu_len,unsigned char * pdu_buf,char field,int minus,int has_w,int width)167*1a3d31e3SAndroid Build Coastguard Worker static void print_field(char *act, struct per_cpu_info *pci,
168*1a3d31e3SAndroid Build Coastguard Worker struct blk_io_trace *t, unsigned long long elapsed,
169*1a3d31e3SAndroid Build Coastguard Worker int pdu_len, unsigned char *pdu_buf, char field,
170*1a3d31e3SAndroid Build Coastguard Worker int minus, int has_w, int width)
171*1a3d31e3SAndroid Build Coastguard Worker {
172*1a3d31e3SAndroid Build Coastguard Worker char format[64];
173*1a3d31e3SAndroid Build Coastguard Worker
174*1a3d31e3SAndroid Build Coastguard Worker if (has_w) {
175*1a3d31e3SAndroid Build Coastguard Worker if (minus)
176*1a3d31e3SAndroid Build Coastguard Worker sprintf(format, "%%-%d", width);
177*1a3d31e3SAndroid Build Coastguard Worker else
178*1a3d31e3SAndroid Build Coastguard Worker sprintf(format, "%%%d", width);
179*1a3d31e3SAndroid Build Coastguard Worker } else
180*1a3d31e3SAndroid Build Coastguard Worker sprintf(format, "%%");
181*1a3d31e3SAndroid Build Coastguard Worker
182*1a3d31e3SAndroid Build Coastguard Worker switch (field) {
183*1a3d31e3SAndroid Build Coastguard Worker case 'a':
184*1a3d31e3SAndroid Build Coastguard Worker fprintf(ofp, strcat(format, "s"), act);
185*1a3d31e3SAndroid Build Coastguard Worker break;
186*1a3d31e3SAndroid Build Coastguard Worker case 'c':
187*1a3d31e3SAndroid Build Coastguard Worker fprintf(ofp, strcat(format, "d"), pci->cpu);
188*1a3d31e3SAndroid Build Coastguard Worker break;
189*1a3d31e3SAndroid Build Coastguard Worker case 'C': {
190*1a3d31e3SAndroid Build Coastguard Worker char *name = find_process_name(t->pid);
191*1a3d31e3SAndroid Build Coastguard Worker
192*1a3d31e3SAndroid Build Coastguard Worker fprintf(ofp, strcat(format, "s"), name);
193*1a3d31e3SAndroid Build Coastguard Worker break;
194*1a3d31e3SAndroid Build Coastguard Worker }
195*1a3d31e3SAndroid Build Coastguard Worker case 'd': {
196*1a3d31e3SAndroid Build Coastguard Worker char rwbs[8];
197*1a3d31e3SAndroid Build Coastguard Worker
198*1a3d31e3SAndroid Build Coastguard Worker fill_rwbs(rwbs, t);
199*1a3d31e3SAndroid Build Coastguard Worker fprintf(ofp, strcat(format, "s"), rwbs);
200*1a3d31e3SAndroid Build Coastguard Worker break;
201*1a3d31e3SAndroid Build Coastguard Worker }
202*1a3d31e3SAndroid Build Coastguard Worker case 'D': /* format width ignored */
203*1a3d31e3SAndroid Build Coastguard Worker fprintf(ofp,"%3d,%-3d", MAJOR(t->device), MINOR(t->device));
204*1a3d31e3SAndroid Build Coastguard Worker break;
205*1a3d31e3SAndroid Build Coastguard Worker case 'e':
206*1a3d31e3SAndroid Build Coastguard Worker fprintf(ofp, strcat(format, "d"), t->error);
207*1a3d31e3SAndroid Build Coastguard Worker break;
208*1a3d31e3SAndroid Build Coastguard Worker case 'M':
209*1a3d31e3SAndroid Build Coastguard Worker fprintf(ofp, strcat(format, "d"), MAJOR(t->device));
210*1a3d31e3SAndroid Build Coastguard Worker break;
211*1a3d31e3SAndroid Build Coastguard Worker case 'm':
212*1a3d31e3SAndroid Build Coastguard Worker fprintf(ofp, strcat(format, "d"), MINOR(t->device));
213*1a3d31e3SAndroid Build Coastguard Worker break;
214*1a3d31e3SAndroid Build Coastguard Worker case 'n':
215*1a3d31e3SAndroid Build Coastguard Worker fprintf(ofp, strcat(format, "u"), t_sec(t));
216*1a3d31e3SAndroid Build Coastguard Worker break;
217*1a3d31e3SAndroid Build Coastguard Worker case 'N':
218*1a3d31e3SAndroid Build Coastguard Worker fprintf(ofp, strcat(format, "u"), t->bytes);
219*1a3d31e3SAndroid Build Coastguard Worker break;
220*1a3d31e3SAndroid Build Coastguard Worker case 'p':
221*1a3d31e3SAndroid Build Coastguard Worker fprintf(ofp, strcat(format, "u"), t->pid);
222*1a3d31e3SAndroid Build Coastguard Worker break;
223*1a3d31e3SAndroid Build Coastguard Worker case 'P': { /* format width ignored */
224*1a3d31e3SAndroid Build Coastguard Worker char *p = dump_pdu(pdu_buf, pdu_len);
225*1a3d31e3SAndroid Build Coastguard Worker if (p)
226*1a3d31e3SAndroid Build Coastguard Worker fprintf(ofp, "%s", p);
227*1a3d31e3SAndroid Build Coastguard Worker break;
228*1a3d31e3SAndroid Build Coastguard Worker }
229*1a3d31e3SAndroid Build Coastguard Worker case 's':
230*1a3d31e3SAndroid Build Coastguard Worker fprintf(ofp, strcat(format, "ld"), t->sequence);
231*1a3d31e3SAndroid Build Coastguard Worker break;
232*1a3d31e3SAndroid Build Coastguard Worker case 'S':
233*1a3d31e3SAndroid Build Coastguard Worker fprintf(ofp, strcat(format, "lu"), t->sector);
234*1a3d31e3SAndroid Build Coastguard Worker break;
235*1a3d31e3SAndroid Build Coastguard Worker case 't':
236*1a3d31e3SAndroid Build Coastguard Worker sprintf(format, "%%0%dlu", has_w ? width : 9);
237*1a3d31e3SAndroid Build Coastguard Worker fprintf(ofp, format, NANO_SECONDS(t->time));
238*1a3d31e3SAndroid Build Coastguard Worker break;
239*1a3d31e3SAndroid Build Coastguard Worker case 'T':
240*1a3d31e3SAndroid Build Coastguard Worker fprintf(ofp, strcat(format, "d"), SECONDS(t->time));
241*1a3d31e3SAndroid Build Coastguard Worker break;
242*1a3d31e3SAndroid Build Coastguard Worker case 'u':
243*1a3d31e3SAndroid Build Coastguard Worker if (elapsed == -1ULL) {
244*1a3d31e3SAndroid Build Coastguard Worker fprintf(stderr, "Expecting elapsed value\n");
245*1a3d31e3SAndroid Build Coastguard Worker exit(1);
246*1a3d31e3SAndroid Build Coastguard Worker }
247*1a3d31e3SAndroid Build Coastguard Worker fprintf(ofp, strcat(format, "llu"), elapsed / 1000);
248*1a3d31e3SAndroid Build Coastguard Worker break;
249*1a3d31e3SAndroid Build Coastguard Worker case 'U':
250*1a3d31e3SAndroid Build Coastguard Worker fprintf(ofp, strcat(format, "u"), get_pdu_int(t));
251*1a3d31e3SAndroid Build Coastguard Worker break;
252*1a3d31e3SAndroid Build Coastguard Worker case 'z':
253*1a3d31e3SAndroid Build Coastguard Worker fprintf(ofp, strcat(format, "s"), print_time(t->time));
254*1a3d31e3SAndroid Build Coastguard Worker break;
255*1a3d31e3SAndroid Build Coastguard Worker default:
256*1a3d31e3SAndroid Build Coastguard Worker fprintf(ofp,strcat(format, "c"), field);
257*1a3d31e3SAndroid Build Coastguard Worker break;
258*1a3d31e3SAndroid Build Coastguard Worker }
259*1a3d31e3SAndroid Build Coastguard Worker }
260*1a3d31e3SAndroid Build Coastguard Worker
parse_field(char * act,struct per_cpu_info * pci,struct blk_io_trace * t,unsigned long long elapsed,int pdu_len,unsigned char * pdu_buf,char * master_format)261*1a3d31e3SAndroid Build Coastguard Worker static char *parse_field(char *act, struct per_cpu_info *pci,
262*1a3d31e3SAndroid Build Coastguard Worker struct blk_io_trace *t, unsigned long long elapsed,
263*1a3d31e3SAndroid Build Coastguard Worker int pdu_len, unsigned char *pdu_buf,
264*1a3d31e3SAndroid Build Coastguard Worker char *master_format)
265*1a3d31e3SAndroid Build Coastguard Worker {
266*1a3d31e3SAndroid Build Coastguard Worker int minus = 0;
267*1a3d31e3SAndroid Build Coastguard Worker int has_w = 0;
268*1a3d31e3SAndroid Build Coastguard Worker int width = 0;
269*1a3d31e3SAndroid Build Coastguard Worker char *p = master_format;
270*1a3d31e3SAndroid Build Coastguard Worker
271*1a3d31e3SAndroid Build Coastguard Worker if (*p == '-') {
272*1a3d31e3SAndroid Build Coastguard Worker minus = 1;
273*1a3d31e3SAndroid Build Coastguard Worker p++;
274*1a3d31e3SAndroid Build Coastguard Worker }
275*1a3d31e3SAndroid Build Coastguard Worker if (isdigit(*p)) {
276*1a3d31e3SAndroid Build Coastguard Worker has_w = 1;
277*1a3d31e3SAndroid Build Coastguard Worker do {
278*1a3d31e3SAndroid Build Coastguard Worker width = (width * 10) + (*p++ - '0');
279*1a3d31e3SAndroid Build Coastguard Worker } while ((*p) && (isdigit(*p)));
280*1a3d31e3SAndroid Build Coastguard Worker }
281*1a3d31e3SAndroid Build Coastguard Worker if (*p) {
282*1a3d31e3SAndroid Build Coastguard Worker print_field(act, pci, t, elapsed, pdu_len, pdu_buf, *p++,
283*1a3d31e3SAndroid Build Coastguard Worker minus, has_w, width);
284*1a3d31e3SAndroid Build Coastguard Worker }
285*1a3d31e3SAndroid Build Coastguard Worker return p;
286*1a3d31e3SAndroid Build Coastguard Worker }
287*1a3d31e3SAndroid Build Coastguard Worker
process_default(char * act,struct per_cpu_info * pci,struct blk_io_trace * t,unsigned long long elapsed,int pdu_len,unsigned char * pdu_buf)288*1a3d31e3SAndroid Build Coastguard Worker static void process_default(char *act, struct per_cpu_info *pci,
289*1a3d31e3SAndroid Build Coastguard Worker struct blk_io_trace *t, unsigned long long elapsed,
290*1a3d31e3SAndroid Build Coastguard Worker int pdu_len, unsigned char *pdu_buf)
291*1a3d31e3SAndroid Build Coastguard Worker {
292*1a3d31e3SAndroid Build Coastguard Worker struct blk_io_trace_remap r = { .device_from = 0, };
293*1a3d31e3SAndroid Build Coastguard Worker char rwbs[8];
294*1a3d31e3SAndroid Build Coastguard Worker char *name;
295*1a3d31e3SAndroid Build Coastguard Worker
296*1a3d31e3SAndroid Build Coastguard Worker fill_rwbs(rwbs, t);
297*1a3d31e3SAndroid Build Coastguard Worker
298*1a3d31e3SAndroid Build Coastguard Worker /*
299*1a3d31e3SAndroid Build Coastguard Worker * For remaps we have to modify the device using the remap structure
300*1a3d31e3SAndroid Build Coastguard Worker * passed up.
301*1a3d31e3SAndroid Build Coastguard Worker */
302*1a3d31e3SAndroid Build Coastguard Worker if (act[0] == 'A') {
303*1a3d31e3SAndroid Build Coastguard Worker get_pdu_remap(t, &r);
304*1a3d31e3SAndroid Build Coastguard Worker t->device = r.device_to;
305*1a3d31e3SAndroid Build Coastguard Worker }
306*1a3d31e3SAndroid Build Coastguard Worker
307*1a3d31e3SAndroid Build Coastguard Worker /*
308*1a3d31e3SAndroid Build Coastguard Worker * The header is always the same
309*1a3d31e3SAndroid Build Coastguard Worker */
310*1a3d31e3SAndroid Build Coastguard Worker fprintf(ofp, "%3d,%-3d %2d %8d %5d.%09lu %5u %2s %3s ",
311*1a3d31e3SAndroid Build Coastguard Worker MAJOR(t->device), MINOR(t->device), pci->cpu, t->sequence,
312*1a3d31e3SAndroid Build Coastguard Worker (int) SECONDS(t->time), (unsigned long) NANO_SECONDS(t->time),
313*1a3d31e3SAndroid Build Coastguard Worker t->pid, act, rwbs);
314*1a3d31e3SAndroid Build Coastguard Worker
315*1a3d31e3SAndroid Build Coastguard Worker name = find_process_name(t->pid);
316*1a3d31e3SAndroid Build Coastguard Worker
317*1a3d31e3SAndroid Build Coastguard Worker switch (act[0]) {
318*1a3d31e3SAndroid Build Coastguard Worker case 'R': /* Requeue */
319*1a3d31e3SAndroid Build Coastguard Worker case 'C': /* Complete */
320*1a3d31e3SAndroid Build Coastguard Worker if (t->action & BLK_TC_ACT(BLK_TC_PC)) {
321*1a3d31e3SAndroid Build Coastguard Worker char *p = dump_pdu(pdu_buf, pdu_len);
322*1a3d31e3SAndroid Build Coastguard Worker if (p)
323*1a3d31e3SAndroid Build Coastguard Worker fprintf(ofp, "(%s) ", p);
324*1a3d31e3SAndroid Build Coastguard Worker fprintf(ofp, "[%d]\n", t->error);
325*1a3d31e3SAndroid Build Coastguard Worker } else {
326*1a3d31e3SAndroid Build Coastguard Worker if (elapsed != -1ULL) {
327*1a3d31e3SAndroid Build Coastguard Worker if (t_sec(t))
328*1a3d31e3SAndroid Build Coastguard Worker fprintf(ofp, "%llu + %u (%8llu) [%d]\n",
329*1a3d31e3SAndroid Build Coastguard Worker (unsigned long long) t->sector,
330*1a3d31e3SAndroid Build Coastguard Worker t_sec(t), elapsed, t->error);
331*1a3d31e3SAndroid Build Coastguard Worker else
332*1a3d31e3SAndroid Build Coastguard Worker fprintf(ofp, "%llu (%8llu) [%d]\n",
333*1a3d31e3SAndroid Build Coastguard Worker (unsigned long long) t->sector,
334*1a3d31e3SAndroid Build Coastguard Worker elapsed, t->error);
335*1a3d31e3SAndroid Build Coastguard Worker } else {
336*1a3d31e3SAndroid Build Coastguard Worker if (t_sec(t))
337*1a3d31e3SAndroid Build Coastguard Worker fprintf(ofp, "%llu + %u [%d]\n",
338*1a3d31e3SAndroid Build Coastguard Worker (unsigned long long) t->sector,
339*1a3d31e3SAndroid Build Coastguard Worker t_sec(t), t->error);
340*1a3d31e3SAndroid Build Coastguard Worker else
341*1a3d31e3SAndroid Build Coastguard Worker fprintf(ofp, "%llu [%d]\n",
342*1a3d31e3SAndroid Build Coastguard Worker (unsigned long long) t->sector,
343*1a3d31e3SAndroid Build Coastguard Worker t->error);
344*1a3d31e3SAndroid Build Coastguard Worker }
345*1a3d31e3SAndroid Build Coastguard Worker }
346*1a3d31e3SAndroid Build Coastguard Worker break;
347*1a3d31e3SAndroid Build Coastguard Worker
348*1a3d31e3SAndroid Build Coastguard Worker case 'D': /* Issue */
349*1a3d31e3SAndroid Build Coastguard Worker case 'I': /* Insert */
350*1a3d31e3SAndroid Build Coastguard Worker case 'Q': /* Queue */
351*1a3d31e3SAndroid Build Coastguard Worker case 'B': /* Bounce */
352*1a3d31e3SAndroid Build Coastguard Worker if (t->action & BLK_TC_ACT(BLK_TC_PC)) {
353*1a3d31e3SAndroid Build Coastguard Worker char *p;
354*1a3d31e3SAndroid Build Coastguard Worker fprintf(ofp, "%u ", t->bytes);
355*1a3d31e3SAndroid Build Coastguard Worker p = dump_pdu(pdu_buf, pdu_len);
356*1a3d31e3SAndroid Build Coastguard Worker if (p)
357*1a3d31e3SAndroid Build Coastguard Worker fprintf(ofp, "(%s) ", p);
358*1a3d31e3SAndroid Build Coastguard Worker fprintf(ofp, "[%s]\n", name);
359*1a3d31e3SAndroid Build Coastguard Worker } else {
360*1a3d31e3SAndroid Build Coastguard Worker if (elapsed != -1ULL) {
361*1a3d31e3SAndroid Build Coastguard Worker if (t_sec(t))
362*1a3d31e3SAndroid Build Coastguard Worker fprintf(ofp, "%llu + %u (%8llu) [%s]\n",
363*1a3d31e3SAndroid Build Coastguard Worker (unsigned long long) t->sector,
364*1a3d31e3SAndroid Build Coastguard Worker t_sec(t), elapsed, name);
365*1a3d31e3SAndroid Build Coastguard Worker else
366*1a3d31e3SAndroid Build Coastguard Worker fprintf(ofp, "(%8llu) [%s]\n", elapsed,
367*1a3d31e3SAndroid Build Coastguard Worker name);
368*1a3d31e3SAndroid Build Coastguard Worker } else {
369*1a3d31e3SAndroid Build Coastguard Worker if (t_sec(t))
370*1a3d31e3SAndroid Build Coastguard Worker fprintf(ofp, "%llu + %u [%s]\n",
371*1a3d31e3SAndroid Build Coastguard Worker (unsigned long long) t->sector,
372*1a3d31e3SAndroid Build Coastguard Worker t_sec(t), name);
373*1a3d31e3SAndroid Build Coastguard Worker else
374*1a3d31e3SAndroid Build Coastguard Worker fprintf(ofp, "[%s]\n", name);
375*1a3d31e3SAndroid Build Coastguard Worker }
376*1a3d31e3SAndroid Build Coastguard Worker }
377*1a3d31e3SAndroid Build Coastguard Worker break;
378*1a3d31e3SAndroid Build Coastguard Worker
379*1a3d31e3SAndroid Build Coastguard Worker case 'M': /* Back merge */
380*1a3d31e3SAndroid Build Coastguard Worker case 'F': /* Front merge */
381*1a3d31e3SAndroid Build Coastguard Worker case 'G': /* Get request */
382*1a3d31e3SAndroid Build Coastguard Worker case 'S': /* Sleep request */
383*1a3d31e3SAndroid Build Coastguard Worker if (t_sec(t))
384*1a3d31e3SAndroid Build Coastguard Worker fprintf(ofp, "%llu + %u [%s]\n",
385*1a3d31e3SAndroid Build Coastguard Worker (unsigned long long) t->sector, t_sec(t), name);
386*1a3d31e3SAndroid Build Coastguard Worker else
387*1a3d31e3SAndroid Build Coastguard Worker fprintf(ofp, "[%s]\n", name);
388*1a3d31e3SAndroid Build Coastguard Worker break;
389*1a3d31e3SAndroid Build Coastguard Worker
390*1a3d31e3SAndroid Build Coastguard Worker case 'P': /* Plug */
391*1a3d31e3SAndroid Build Coastguard Worker fprintf(ofp, "[%s]\n", name);
392*1a3d31e3SAndroid Build Coastguard Worker break;
393*1a3d31e3SAndroid Build Coastguard Worker
394*1a3d31e3SAndroid Build Coastguard Worker case 'U': /* Unplug IO */
395*1a3d31e3SAndroid Build Coastguard Worker case 'T': /* Unplug timer */
396*1a3d31e3SAndroid Build Coastguard Worker fprintf(ofp, "[%s] %u\n", name, get_pdu_int(t));
397*1a3d31e3SAndroid Build Coastguard Worker break;
398*1a3d31e3SAndroid Build Coastguard Worker
399*1a3d31e3SAndroid Build Coastguard Worker case 'A': /* remap */
400*1a3d31e3SAndroid Build Coastguard Worker get_pdu_remap(t, &r);
401*1a3d31e3SAndroid Build Coastguard Worker fprintf(ofp, "%llu + %u <- (%d,%d) %llu\n",
402*1a3d31e3SAndroid Build Coastguard Worker (unsigned long long) t->sector, t_sec(t),
403*1a3d31e3SAndroid Build Coastguard Worker MAJOR(r.device_from), MINOR(r.device_from),
404*1a3d31e3SAndroid Build Coastguard Worker (unsigned long long) r.sector_from);
405*1a3d31e3SAndroid Build Coastguard Worker break;
406*1a3d31e3SAndroid Build Coastguard Worker
407*1a3d31e3SAndroid Build Coastguard Worker case 'X': /* Split */
408*1a3d31e3SAndroid Build Coastguard Worker fprintf(ofp, "%llu / %u [%s]\n", (unsigned long long) t->sector,
409*1a3d31e3SAndroid Build Coastguard Worker get_pdu_int(t), name);
410*1a3d31e3SAndroid Build Coastguard Worker break;
411*1a3d31e3SAndroid Build Coastguard Worker
412*1a3d31e3SAndroid Build Coastguard Worker case 'm': /* Message */
413*1a3d31e3SAndroid Build Coastguard Worker fprintf(ofp, "%*s\n", pdu_len, pdu_buf);
414*1a3d31e3SAndroid Build Coastguard Worker break;
415*1a3d31e3SAndroid Build Coastguard Worker
416*1a3d31e3SAndroid Build Coastguard Worker default:
417*1a3d31e3SAndroid Build Coastguard Worker fprintf(stderr, "Unknown action %c\n", act[0]);
418*1a3d31e3SAndroid Build Coastguard Worker break;
419*1a3d31e3SAndroid Build Coastguard Worker }
420*1a3d31e3SAndroid Build Coastguard Worker
421*1a3d31e3SAndroid Build Coastguard Worker }
422*1a3d31e3SAndroid Build Coastguard Worker
process_fmt(char * act,struct per_cpu_info * pci,struct blk_io_trace * t,unsigned long long elapsed,int pdu_len,unsigned char * pdu_buf)423*1a3d31e3SAndroid Build Coastguard Worker void process_fmt(char *act, struct per_cpu_info *pci, struct blk_io_trace *t,
424*1a3d31e3SAndroid Build Coastguard Worker unsigned long long elapsed, int pdu_len,
425*1a3d31e3SAndroid Build Coastguard Worker unsigned char *pdu_buf)
426*1a3d31e3SAndroid Build Coastguard Worker {
427*1a3d31e3SAndroid Build Coastguard Worker char *p = override_format[(int) *act];
428*1a3d31e3SAndroid Build Coastguard Worker
429*1a3d31e3SAndroid Build Coastguard Worker if (!p) {
430*1a3d31e3SAndroid Build Coastguard Worker process_default(act, pci, t, elapsed, pdu_len, pdu_buf);
431*1a3d31e3SAndroid Build Coastguard Worker return;
432*1a3d31e3SAndroid Build Coastguard Worker }
433*1a3d31e3SAndroid Build Coastguard Worker
434*1a3d31e3SAndroid Build Coastguard Worker while (*p) {
435*1a3d31e3SAndroid Build Coastguard Worker switch (*p) {
436*1a3d31e3SAndroid Build Coastguard Worker case '%': /* Field specifier */
437*1a3d31e3SAndroid Build Coastguard Worker p++;
438*1a3d31e3SAndroid Build Coastguard Worker if (*p == '%')
439*1a3d31e3SAndroid Build Coastguard Worker fprintf(ofp, "%c", *p++);
440*1a3d31e3SAndroid Build Coastguard Worker else if (!*p)
441*1a3d31e3SAndroid Build Coastguard Worker fprintf(ofp, "%c", '%');
442*1a3d31e3SAndroid Build Coastguard Worker else
443*1a3d31e3SAndroid Build Coastguard Worker p = parse_field(act, pci, t, elapsed,
444*1a3d31e3SAndroid Build Coastguard Worker pdu_len, pdu_buf, p);
445*1a3d31e3SAndroid Build Coastguard Worker break;
446*1a3d31e3SAndroid Build Coastguard Worker case '\\': { /* escape */
447*1a3d31e3SAndroid Build Coastguard Worker switch (p[1]) {
448*1a3d31e3SAndroid Build Coastguard Worker case 'b': fprintf(ofp, "\b"); break;
449*1a3d31e3SAndroid Build Coastguard Worker case 'n': fprintf(ofp, "\n"); break;
450*1a3d31e3SAndroid Build Coastguard Worker case 'r': fprintf(ofp, "\r"); break;
451*1a3d31e3SAndroid Build Coastguard Worker case 't': fprintf(ofp, "\t"); break;
452*1a3d31e3SAndroid Build Coastguard Worker default:
453*1a3d31e3SAndroid Build Coastguard Worker fprintf(stderr,
454*1a3d31e3SAndroid Build Coastguard Worker "Invalid escape char in format %c\n",
455*1a3d31e3SAndroid Build Coastguard Worker p[1]);
456*1a3d31e3SAndroid Build Coastguard Worker exit(1);
457*1a3d31e3SAndroid Build Coastguard Worker /*NOTREACHED*/
458*1a3d31e3SAndroid Build Coastguard Worker }
459*1a3d31e3SAndroid Build Coastguard Worker p += 2;
460*1a3d31e3SAndroid Build Coastguard Worker break;
461*1a3d31e3SAndroid Build Coastguard Worker }
462*1a3d31e3SAndroid Build Coastguard Worker default:
463*1a3d31e3SAndroid Build Coastguard Worker fprintf(ofp, "%c", *p++);
464*1a3d31e3SAndroid Build Coastguard Worker break;
465*1a3d31e3SAndroid Build Coastguard Worker }
466*1a3d31e3SAndroid Build Coastguard Worker }
467*1a3d31e3SAndroid Build Coastguard Worker }
468*1a3d31e3SAndroid Build Coastguard Worker
469*1a3d31e3SAndroid Build Coastguard Worker
470