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