xref: /minix3/minix/usr.sbin/btrace/btrace.c (revision 964427e0ea7f92f694a9ea097fe466d71ba3a83e)
1*964427e0SDavid van Moolenbroek /* Block trace command line tool - by D.C. van Moolenbroek */
2*964427e0SDavid van Moolenbroek #include <stdlib.h>
3*964427e0SDavid van Moolenbroek #include <stdio.h>
4*964427e0SDavid van Moolenbroek #include <string.h>
5*964427e0SDavid van Moolenbroek #include <unistd.h>
6*964427e0SDavid van Moolenbroek #include <fcntl.h>
7*964427e0SDavid van Moolenbroek #include <sys/types.h>
8*964427e0SDavid van Moolenbroek #include <minix/btrace.h>
9*964427e0SDavid van Moolenbroek #include <minix/u64.h>
10*964427e0SDavid van Moolenbroek #include <sys/ioctl.h>
11*964427e0SDavid van Moolenbroek 
12*964427e0SDavid van Moolenbroek static btrace_entry buf[BTBUF_SIZE];
13*964427e0SDavid van Moolenbroek 
14*964427e0SDavid van Moolenbroek static void __dead
usage(void)15*964427e0SDavid van Moolenbroek usage(void)
16*964427e0SDavid van Moolenbroek {
17*964427e0SDavid van Moolenbroek 	fprintf(stderr, "usage:\n"
18*964427e0SDavid van Moolenbroek 	    "%s start <device> <nr_entries>\n"
19*964427e0SDavid van Moolenbroek 	    "%s stop <device> <file>\n"
20*964427e0SDavid van Moolenbroek 	    "%s reset <device>\n"
21*964427e0SDavid van Moolenbroek 	    "%s dump <file>\n",
22*964427e0SDavid van Moolenbroek 	    getprogname(), getprogname(), getprogname(), getprogname());
23*964427e0SDavid van Moolenbroek 
24*964427e0SDavid van Moolenbroek 	exit(EXIT_FAILURE);
25*964427e0SDavid van Moolenbroek }
26*964427e0SDavid van Moolenbroek 
27*964427e0SDavid van Moolenbroek static void
btrace_start(char * device,int nr_entries)28*964427e0SDavid van Moolenbroek btrace_start(char * device, int nr_entries)
29*964427e0SDavid van Moolenbroek {
30*964427e0SDavid van Moolenbroek 	int r, ctl, devfd;
31*964427e0SDavid van Moolenbroek 	size_t size;
32*964427e0SDavid van Moolenbroek 
33*964427e0SDavid van Moolenbroek 	if ((devfd = open(device, O_RDONLY)) < 0) {
34*964427e0SDavid van Moolenbroek 		perror("device open");
35*964427e0SDavid van Moolenbroek 		exit(EXIT_FAILURE);
36*964427e0SDavid van Moolenbroek 	}
37*964427e0SDavid van Moolenbroek 
38*964427e0SDavid van Moolenbroek 	size = nr_entries;
39*964427e0SDavid van Moolenbroek 	if ((r = ioctl(devfd, BIOCTRACEBUF, &size)) < 0) {
40*964427e0SDavid van Moolenbroek 		perror("ioctl(BIOCTRACEBUF)");
41*964427e0SDavid van Moolenbroek 		exit(EXIT_FAILURE);
42*964427e0SDavid van Moolenbroek 	}
43*964427e0SDavid van Moolenbroek 
44*964427e0SDavid van Moolenbroek 	ctl = BTCTL_START;
45*964427e0SDavid van Moolenbroek 	if ((r = ioctl(devfd, BIOCTRACECTL, &ctl)) < 0) {
46*964427e0SDavid van Moolenbroek 		perror("ioctl(BIOCTRACECTL)");
47*964427e0SDavid van Moolenbroek 
48*964427e0SDavid van Moolenbroek 		size = 0;
49*964427e0SDavid van Moolenbroek 		(void)ioctl(devfd, BIOCTRACEBUF, &size);
50*964427e0SDavid van Moolenbroek 
51*964427e0SDavid van Moolenbroek 		exit(EXIT_FAILURE);
52*964427e0SDavid van Moolenbroek 	}
53*964427e0SDavid van Moolenbroek 
54*964427e0SDavid van Moolenbroek 	close(devfd);
55*964427e0SDavid van Moolenbroek }
56*964427e0SDavid van Moolenbroek 
57*964427e0SDavid van Moolenbroek static void
btrace_stop(char * device,char * file)58*964427e0SDavid van Moolenbroek btrace_stop(char * device, char * file)
59*964427e0SDavid van Moolenbroek {
60*964427e0SDavid van Moolenbroek 	int r, ctl, devfd, outfd;
61*964427e0SDavid van Moolenbroek 	size_t size;
62*964427e0SDavid van Moolenbroek 
63*964427e0SDavid van Moolenbroek 	if ((devfd = open(device, O_RDONLY)) < 0) {
64*964427e0SDavid van Moolenbroek 		perror("device open");
65*964427e0SDavid van Moolenbroek 		exit(EXIT_FAILURE);
66*964427e0SDavid van Moolenbroek 	}
67*964427e0SDavid van Moolenbroek 
68*964427e0SDavid van Moolenbroek 	if ((outfd = open(file, O_CREAT | O_TRUNC | O_WRONLY, 0600)) < 0) {
69*964427e0SDavid van Moolenbroek 		perror("file open");
70*964427e0SDavid van Moolenbroek 		exit(EXIT_FAILURE);
71*964427e0SDavid van Moolenbroek 	  }
72*964427e0SDavid van Moolenbroek 
73*964427e0SDavid van Moolenbroek 	ctl = BTCTL_STOP;
74*964427e0SDavid van Moolenbroek 	if ((r = ioctl(devfd, BIOCTRACECTL, &ctl)) < 0) {
75*964427e0SDavid van Moolenbroek 		perror("ioctl(BIOCTRACECTL)");
76*964427e0SDavid van Moolenbroek 		exit(EXIT_FAILURE);
77*964427e0SDavid van Moolenbroek 	}
78*964427e0SDavid van Moolenbroek 
79*964427e0SDavid van Moolenbroek 	for (;;) {
80*964427e0SDavid van Moolenbroek 		if ((r = ioctl(devfd, BIOCTRACEGET, buf)) < 0) {
81*964427e0SDavid van Moolenbroek 			perror("ioctl(BIOCTRACEGET)");
82*964427e0SDavid van Moolenbroek 			break;
83*964427e0SDavid van Moolenbroek 		}
84*964427e0SDavid van Moolenbroek 
85*964427e0SDavid van Moolenbroek 		if (r == 0) break;
86*964427e0SDavid van Moolenbroek 
87*964427e0SDavid van Moolenbroek 		size = r * sizeof(buf[0]);
88*964427e0SDavid van Moolenbroek 		if ((r = write(outfd, (char *)buf, size)) != size) {
89*964427e0SDavid van Moolenbroek 			if (r < 0) perror("write");
90*964427e0SDavid van Moolenbroek 			else fputs("short write\n", stderr);
91*964427e0SDavid van Moolenbroek 		}
92*964427e0SDavid van Moolenbroek 	}
93*964427e0SDavid van Moolenbroek 
94*964427e0SDavid van Moolenbroek 	close(outfd);
95*964427e0SDavid van Moolenbroek 
96*964427e0SDavid van Moolenbroek 	size = 0;
97*964427e0SDavid van Moolenbroek 	if ((r = ioctl(devfd, BIOCTRACEBUF, &size)) < 0) {
98*964427e0SDavid van Moolenbroek 		perror("ioctl(BIOCTRACEBUF)");
99*964427e0SDavid van Moolenbroek 		exit(EXIT_FAILURE);
100*964427e0SDavid van Moolenbroek 	}
101*964427e0SDavid van Moolenbroek 
102*964427e0SDavid van Moolenbroek 	close(devfd);
103*964427e0SDavid van Moolenbroek }
104*964427e0SDavid van Moolenbroek 
105*964427e0SDavid van Moolenbroek static void
btrace_reset(char * device)106*964427e0SDavid van Moolenbroek btrace_reset(char * device)
107*964427e0SDavid van Moolenbroek {
108*964427e0SDavid van Moolenbroek 	size_t size;
109*964427e0SDavid van Moolenbroek 	int r, ctl, devfd;
110*964427e0SDavid van Moolenbroek 
111*964427e0SDavid van Moolenbroek 	if ((devfd = open(device, O_RDONLY)) < 0) {
112*964427e0SDavid van Moolenbroek 		perror("device open");
113*964427e0SDavid van Moolenbroek 		exit(EXIT_FAILURE);
114*964427e0SDavid van Moolenbroek 	}
115*964427e0SDavid van Moolenbroek 
116*964427e0SDavid van Moolenbroek 	ctl = BTCTL_STOP;
117*964427e0SDavid van Moolenbroek 	(void)ioctl(devfd, BIOCTRACECTL, &ctl);
118*964427e0SDavid van Moolenbroek 
119*964427e0SDavid van Moolenbroek 	size = 0;
120*964427e0SDavid van Moolenbroek 	if ((r = ioctl(devfd, BIOCTRACEBUF, &size)) < 0) {
121*964427e0SDavid van Moolenbroek 		perror("ioctl(BIOCTRACEBUF)");
122*964427e0SDavid van Moolenbroek 		exit(EXIT_FAILURE);
123*964427e0SDavid van Moolenbroek 	}
124*964427e0SDavid van Moolenbroek 
125*964427e0SDavid van Moolenbroek 	close(devfd);
126*964427e0SDavid van Moolenbroek }
127*964427e0SDavid van Moolenbroek 
128*964427e0SDavid van Moolenbroek static void
dump_entry(btrace_entry * entry)129*964427e0SDavid van Moolenbroek dump_entry(btrace_entry * entry)
130*964427e0SDavid van Moolenbroek {
131*964427e0SDavid van Moolenbroek 	switch (entry->request) {
132*964427e0SDavid van Moolenbroek 	case BTREQ_OPEN: printf("OPEN"); break;
133*964427e0SDavid van Moolenbroek 	case BTREQ_CLOSE: printf("CLOSE"); break;
134*964427e0SDavid van Moolenbroek 	case BTREQ_READ: printf("READ"); break;
135*964427e0SDavid van Moolenbroek 	case BTREQ_WRITE: printf("WRITE"); break;
136*964427e0SDavid van Moolenbroek 	case BTREQ_GATHER: printf("GATHER"); break;
137*964427e0SDavid van Moolenbroek 	case BTREQ_SCATTER: printf("SCATTER"); break;
138*964427e0SDavid van Moolenbroek 	case BTREQ_IOCTL: printf("IOCTL"); break;
139*964427e0SDavid van Moolenbroek 	}
140*964427e0SDavid van Moolenbroek 
141*964427e0SDavid van Moolenbroek 	printf(" request\n");
142*964427e0SDavid van Moolenbroek 
143*964427e0SDavid van Moolenbroek 	switch (entry->request) {
144*964427e0SDavid van Moolenbroek 	case BTREQ_OPEN:
145*964427e0SDavid van Moolenbroek 		printf("- access:\t%x\n", entry->size);
146*964427e0SDavid van Moolenbroek 		break;
147*964427e0SDavid van Moolenbroek 	case BTREQ_READ:
148*964427e0SDavid van Moolenbroek 	case BTREQ_WRITE:
149*964427e0SDavid van Moolenbroek 	case BTREQ_GATHER:
150*964427e0SDavid van Moolenbroek 	case BTREQ_SCATTER:
151*964427e0SDavid van Moolenbroek 		printf("- position:\t%08lx%08lx\n",
152*964427e0SDavid van Moolenbroek 		    ex64hi(entry->position), ex64lo(entry->position));
153*964427e0SDavid van Moolenbroek 		printf("- size:\t\t%u\n", entry->size);
154*964427e0SDavid van Moolenbroek 		printf("- flags:\t%x\n", entry->flags);
155*964427e0SDavid van Moolenbroek 		break;
156*964427e0SDavid van Moolenbroek 	case BTREQ_IOCTL:
157*964427e0SDavid van Moolenbroek 		printf("- request:\t%08x\n", entry->size);
158*964427e0SDavid van Moolenbroek 		break;
159*964427e0SDavid van Moolenbroek 	}
160*964427e0SDavid van Moolenbroek 
161*964427e0SDavid van Moolenbroek 	printf("- start:\t%u us\n", entry->start_time);
162*964427e0SDavid van Moolenbroek 	printf("- finish:\t%u us\n", entry->finish_time);
163*964427e0SDavid van Moolenbroek 	if (entry->result == BTRES_INPROGRESS)
164*964427e0SDavid van Moolenbroek 		printf("- result:\t(in progress)\n");
165*964427e0SDavid van Moolenbroek 	else
166*964427e0SDavid van Moolenbroek 		printf("- result:\t%d\n", entry->result);
167*964427e0SDavid van Moolenbroek 	printf("\n");
168*964427e0SDavid van Moolenbroek }
169*964427e0SDavid van Moolenbroek 
170*964427e0SDavid van Moolenbroek static void
btrace_dump(char * file)171*964427e0SDavid van Moolenbroek btrace_dump(char * file)
172*964427e0SDavid van Moolenbroek {
173*964427e0SDavid van Moolenbroek 	int i, r, infd;
174*964427e0SDavid van Moolenbroek 
175*964427e0SDavid van Moolenbroek 	if ((infd = open(file, O_RDONLY)) < 0) {
176*964427e0SDavid van Moolenbroek 		perror("open");
177*964427e0SDavid van Moolenbroek 		exit(EXIT_FAILURE);
178*964427e0SDavid van Moolenbroek 	}
179*964427e0SDavid van Moolenbroek 
180*964427e0SDavid van Moolenbroek 	for (;;) {
181*964427e0SDavid van Moolenbroek 		if ((r = read(infd, (char *)buf, sizeof(buf))) <= 0)
182*964427e0SDavid van Moolenbroek 			break;
183*964427e0SDavid van Moolenbroek 
184*964427e0SDavid van Moolenbroek 		r /= sizeof(buf[0]);
185*964427e0SDavid van Moolenbroek 
186*964427e0SDavid van Moolenbroek 		for (i = 0; i < r; i++)
187*964427e0SDavid van Moolenbroek 			dump_entry(&buf[i]);
188*964427e0SDavid van Moolenbroek 	}
189*964427e0SDavid van Moolenbroek 
190*964427e0SDavid van Moolenbroek 	if (r < 0) perror("read");
191*964427e0SDavid van Moolenbroek 
192*964427e0SDavid van Moolenbroek 	close(infd);
193*964427e0SDavid van Moolenbroek }
194*964427e0SDavid van Moolenbroek 
main(int argc,char ** argv)195*964427e0SDavid van Moolenbroek int main(int argc, char ** argv)
196*964427e0SDavid van Moolenbroek {
197*964427e0SDavid van Moolenbroek 	int num;
198*964427e0SDavid van Moolenbroek 
199*964427e0SDavid van Moolenbroek 	setprogname(argv[0]);
200*964427e0SDavid van Moolenbroek 
201*964427e0SDavid van Moolenbroek 	if (argc < 3) usage();
202*964427e0SDavid van Moolenbroek 
203*964427e0SDavid van Moolenbroek 	if (!strcmp(argv[1], "start")) {
204*964427e0SDavid van Moolenbroek 		if (argc < 4) usage();
205*964427e0SDavid van Moolenbroek 
206*964427e0SDavid van Moolenbroek 		num = atoi(argv[3]);
207*964427e0SDavid van Moolenbroek 
208*964427e0SDavid van Moolenbroek 		if (num <= 0) usage();
209*964427e0SDavid van Moolenbroek 
210*964427e0SDavid van Moolenbroek 		btrace_start(argv[2], num);
211*964427e0SDavid van Moolenbroek 
212*964427e0SDavid van Moolenbroek 	} else if (!strcmp(argv[1], "stop")) {
213*964427e0SDavid van Moolenbroek 		if (argc < 4) usage();
214*964427e0SDavid van Moolenbroek 
215*964427e0SDavid van Moolenbroek 		btrace_stop(argv[2], argv[3]);
216*964427e0SDavid van Moolenbroek 
217*964427e0SDavid van Moolenbroek 	} else if (!strcmp(argv[1], "reset")) {
218*964427e0SDavid van Moolenbroek 		btrace_reset(argv[2]);
219*964427e0SDavid van Moolenbroek 
220*964427e0SDavid van Moolenbroek 	} else if (!strcmp(argv[1], "dump")) {
221*964427e0SDavid van Moolenbroek 		btrace_dump(argv[2]);
222*964427e0SDavid van Moolenbroek 
223*964427e0SDavid van Moolenbroek 	} else
224*964427e0SDavid van Moolenbroek 		usage();
225*964427e0SDavid van Moolenbroek 
226*964427e0SDavid van Moolenbroek 	return EXIT_SUCCESS;
227*964427e0SDavid van Moolenbroek }
228