2 * block queue tracing application
4 * TODO (in no particular order):
5 * - Add ability to specify capture mask instead of logging all events
6 * - Add option for relayfs mount point
10 #include <sys/types.h>
17 #include <sys/ioctl.h>
24 #define BUF_SIZE (128 *1024)
27 struct thread_information {
30 unsigned long events_processed;
33 static char relay_path[] = "/relay/";
35 #define is_done() (*(volatile int *)(&done))
36 static volatile int done;
38 static int devfd, ncpus;
39 static struct thread_information *thread_information;
40 static char *buts_name_p;
42 static int start_trace(char *dev)
44 struct blk_user_trace_setup buts;
46 devfd = open(dev, O_RDONLY);
52 memset(&buts, sizeof(buts), 0);
53 buts.buf_size = BUF_SIZE;
56 printf("Starting trace on %s\n", dev);
57 if (ioctl(devfd, BLKSTARTTRACE, &buts) < 0) {
58 perror("BLKSTARTTRACE");
62 buts_name_p = strdup(buts.name);
66 static void stop_trace(void)
68 if (ioctl(devfd, BLKSTOPTRACE) < 0)
69 perror("BLKSTOPTRACE");
74 static void extract_data(int cpu, char *ifn, int ifd, char *ofn, int ofd,
78 unsigned char *buf, *p;
83 while (bytes_left > 0) {
84 ret = read(ifd, p, bytes_left);
89 fprintf(stderr, "Thread %d extract_data %s failed\n",
99 ret = write(ofd, buf, nb);
102 fprintf(stderr,"Thread %d extract_data %s failed\n", cpu, ofn);
110 static void *extract(void *arg)
112 struct thread_information *tip = arg;
113 int tracefd, ret, ofd;
114 char ip[64], op[64], dp[64];
115 struct blk_io_trace t;
116 pid_t pid = getpid();
120 CPU_SET(tip->cpu, &cpu_mask);
122 if (sched_setaffinity(pid, sizeof(cpu_mask), &cpu_mask) == -1) {
123 perror("sched_setaffinity");
127 sprintf(op, "%s_out.%d", buts_name_p, tip->cpu);
128 ofd = open(op, O_CREAT|O_TRUNC|O_WRONLY, 0644);
131 fprintf(stderr,"Thread %d failed creat of %s\n", tip->cpu, op);
135 sprintf(ip, "%s%s%d", relay_path, buts_name_p, tip->cpu);
136 tracefd = open(ip, O_RDONLY);
139 fprintf(stderr,"Thread %d failed open of %s\n", tip->cpu, ip);
144 ret = read(tracefd, &t, sizeof(t));
145 if (ret != sizeof(t)) {
148 fprintf(stderr,"Thread %d failed read of %s\n",
151 } else if (ret > 0) {
152 fprintf(stderr,"Thread %d misread %s %d,%d\n",
153 tip->cpu, ip, ret, (int)sizeof(t));
161 if (verify_trace(&t))
166 ret = write(ofd, &t, sizeof(t));
169 fprintf(stderr,"Thread %d failed write of %s\n",
175 extract_data(tip->cpu, ip, tracefd, dp, ofd, t.pdu_len);
177 tip->events_processed++;
183 static int start_threads(void)
185 struct thread_information *tip;
188 ncpus = sysconf(_SC_NPROCESSORS_ONLN);
190 fprintf(stderr, "sysconf(_SC_NPROCESSORS_ONLN) failed\n");
193 printf("Processors online: %d\n", ncpus);
195 thread_information = malloc(ncpus * sizeof(struct thread_information));
196 for (i = 0, tip = thread_information; i < ncpus; i++, tip++) {
198 tip->events_processed = 0;
200 if (pthread_create(&tip->thread, NULL, extract, tip)) {
201 perror( "pthread_create");
209 static void stop_threads(void)
211 struct thread_information *tip = thread_information;
214 for (i = 0; i < ncpus; i++, tip++) {
217 if (pthread_join(tip->thread, (void *) &ret))
218 perror("thread_join");
222 void show_stats(void)
225 struct thread_information *tip;
226 unsigned long events_processed = 0;
228 for (i = 0, tip = thread_information; i < ncpus; i++, tip++) {
229 printf("CPU%3d: %20ld events\n",
230 tip->cpu, tip->events_processed);
231 events_processed += tip->events_processed;
234 printf("Total: %20ld events\n", events_processed);
237 void handle_sigint(int sig)
239 printf("exiting on signal %d\n", sig);
243 int main(int argc, char *argv[])
249 fprintf(stderr, "Usage: %s <dev>\n", argv[0]);
253 if (stat(relay_path, &st) < 0) {
254 fprintf(stderr,"%s does not appear to be mounted\n",
259 if (start_trace(argv[1])) {
260 fprintf(stderr, "Failed to start trace\n");
265 setlocale(LC_NUMERIC, "en_US");
269 fprintf(stderr, "Failed to start worker threads\n");
274 printf("Threads started : %d\n", i);
276 signal(SIGINT, handle_sigint);
277 signal(SIGHUP, handle_sigint);
278 signal(SIGTERM, handle_sigint);