xref: /aosp_15_r20/external/blktrace/blkparse_fmt.c (revision 1a3d31e37cc95e9919fd86900a2b6a555f55952c)
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