unstack, sort: cleanup and improvement
[minix.git] / commands / btrace / btrace.c
blobdbdf508e933dd7371d149a3e6ea6f2247c253eff
1 /* Block trace command line tool */
2 #include <stdlib.h>
3 #include <stdio.h>
4 #include <string.h>
5 #include <unistd.h>
6 #include <fcntl.h>
7 #include <minix/types.h>
8 #include <minix/btrace.h>
9 #include <minix/u64.h>
10 #include <sys/ioc_block.h>
12 static btrace_entry buf[BTBUF_SIZE];
14 static void usage(char *name)
16 printf("usage:\n"
17 "%s start <device> <nr_entries>\n"
18 "%s stop <device> <file>\n"
19 "%s reset <device>\n"
20 "%s dump <file>\n",
21 name, name, name, name);
23 exit(EXIT_FAILURE);
26 static void btrace_start(char *device, int nr_entries)
28 int r, ctl, devfd;
29 size_t size;
31 if ((devfd = open(device, O_RDONLY)) < 0) {
32 perror("device open");
33 exit(EXIT_FAILURE);
36 size = nr_entries;
37 if ((r = ioctl(devfd, BIOCTRACEBUF, &size)) < 0) {
38 perror("ioctl(BIOCTRACEBUF)");
39 exit(EXIT_FAILURE);
42 ctl = BTCTL_START;
43 if ((r = ioctl(devfd, BIOCTRACECTL, &ctl)) < 0) {
44 perror("ioctl(BIOCTRACECTL)");
46 size = 0;
47 (void) ioctl(devfd, BIOCTRACEBUF, &size);
49 exit(EXIT_FAILURE);
52 close(devfd);
55 static void btrace_stop(char *device, char *file)
57 int r, ctl, devfd, outfd;
58 size_t size;
60 if ((devfd = open(device, O_RDONLY)) < 0) {
61 perror("device open");
62 exit(EXIT_FAILURE);
65 if ((outfd = open(file, O_CREAT|O_TRUNC|O_WRONLY, 0600)) < 0) {
66 perror("file open");
67 exit(EXIT_FAILURE);
70 ctl = BTCTL_STOP;
71 if ((r = ioctl(devfd, BIOCTRACECTL, &ctl)) < 0) {
72 perror("ioctl(BIOCTRACECTL)");
73 exit(EXIT_FAILURE);
76 for (;;) {
77 if ((r = ioctl(devfd, BIOCTRACEGET, buf)) < 0) {
78 perror("ioctl(BIOCTRACEGET)");
79 break;
82 if (r == 0) break;
84 size = r * sizeof(buf[0]);
85 if ((r = write(outfd, (char *) buf, size)) != size) {
86 if (r < 0) perror("write");
87 else fputs("short write\n", stderr);
91 close(outfd);
93 size = 0;
94 if ((r = ioctl(devfd, BIOCTRACEBUF, &size)) < 0) {
95 perror("ioctl(BIOCTRACEBUF)");
96 exit(EXIT_FAILURE);
99 close(devfd);
102 static void btrace_reset(char *device)
104 size_t size;
105 int r, ctl, devfd;
107 if ((devfd = open(device, O_RDONLY)) < 0) {
108 perror("device open");
109 exit(EXIT_FAILURE);
112 ctl = BTCTL_STOP;
113 (void) ioctl(devfd, BIOCTRACECTL, &ctl);
115 size = 0;
116 if ((r = ioctl(devfd, BIOCTRACEBUF, &size)) < 0) {
117 perror("ioctl(BIOCTRACEBUF)");
118 exit(EXIT_FAILURE);
121 close(devfd);
124 static void dump_entry(btrace_entry *entry)
126 switch (entry->request) {
127 case BTREQ_OPEN: printf("OPEN"); break;
128 case BTREQ_CLOSE: printf("CLOSE"); break;
129 case BTREQ_READ: printf("READ"); break;
130 case BTREQ_WRITE: printf("WRITE"); break;
131 case BTREQ_GATHER: printf("GATHER"); break;
132 case BTREQ_SCATTER: printf("SCATTER"); break;
133 case BTREQ_IOCTL: printf("IOCTL"); break;
136 printf(" request\n");
138 switch (entry->request) {
139 case BTREQ_OPEN:
140 printf("- access:\t%x\n", entry->size);
141 break;
142 case BTREQ_READ:
143 case BTREQ_WRITE:
144 case BTREQ_GATHER:
145 case BTREQ_SCATTER:
146 printf("- position:\t%08lx%08lx\n",
147 ex64hi(entry->position), ex64lo(entry->position));
148 printf("- size:\t\t%u\n", entry->size);
149 printf("- flags:\t%x\n", entry->flags);
150 break;
151 case BTREQ_IOCTL:
152 printf("- request:\t%08x\n", entry->size);
153 break;
156 printf("- start:\t%u us\n", entry->start_time);
157 printf("- finish:\t%u us\n", entry->finish_time);
158 if (entry->result == BTRES_INPROGRESS)
159 printf("- result:\t(in progress)\n");
160 else
161 printf("- result:\t%d\n", entry->result);
162 printf("\n");
165 static void btrace_dump(char *file)
167 int i, r, infd;
169 if ((infd = open(file, O_RDONLY)) < 0) {
170 perror("open");
171 exit(EXIT_FAILURE);
174 for (;;) {
175 if ((r = read(infd, (char *) buf, sizeof(buf))) <= 0)
176 break;
178 r /= sizeof(buf[0]);
180 for (i = 0; i < r; i++)
181 dump_entry(&buf[i]);
184 if (r < 0) perror("read");
186 close(infd);
189 int main(int argc, char **argv)
191 int num;
192 char *name = argv[0];
194 if (argc < 3) usage(name);
196 if (!strcmp(argv[1], "start")) {
197 if (argc < 4) usage(name);
199 num = atoi(argv[3]);
201 if (num <= 0) usage(name);
203 btrace_start(argv[2], num);
205 else if (!strcmp(argv[1], "stop")) {
206 if (argc < 4) usage(name);
208 btrace_stop(argv[2], argv[3]);
210 else if (!strcmp(argv[1], "reset")) {
211 btrace_reset(argv[2]);
213 else if (!strcmp(argv[1], "dump")) {
214 btrace_dump(argv[2]);
216 else usage(name);
218 return EXIT_SUCCESS;