c9141f6711e74244b6de988938c89b2eb4e3b1cd
[fio.git] / blktrace.c
1 /*
2  * blktrace support code for fio
3  */
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include "list.h"
7 #include "fio.h"
8 #include "blktrace_api.h"
9
10 static int discard_pdu(int fd, struct blk_io_trace *t)
11 {
12         if (t->pdu_len == 0)
13                 return 0;
14
15         if (lseek(fd, t->pdu_len, SEEK_CUR) < 0)
16                 return errno;
17                 
18         return 0;
19 }
20
21 int is_blktrace(const char *filename)
22 {
23         struct blk_io_trace t;
24         int fd, ret;
25
26         fd = open(filename, O_RDONLY);
27         if (fd < 0) {
28                 perror("open blktrace");
29                 return 0;
30         }
31
32         ret = read(fd, &t, sizeof(t));
33         close(fd);
34
35         if (ret < 0) {
36                 perror("read blktrace");
37                 return 0;
38         } else if (ret != sizeof(t)) {
39                 log_err("fio: short read on blktrace file\n");
40                 return 0;
41         }
42
43         if ((t.magic & 0xffffff00) == BLK_IO_TRACE_MAGIC)
44                 return 1;
45
46         return 0;
47 }
48
49 static void store_ipo(struct thread_data *td, unsigned long long offset,
50                       unsigned int bytes, int rw)
51 {
52         struct io_piece *ipo = malloc(sizeof(*ipo));
53
54         memset(ipo, 0, sizeof(*ipo));
55         INIT_LIST_HEAD(&ipo->list);
56         ipo->offset = offset;
57         ipo->len = bytes;
58         if (rw)
59                 ipo->ddir = DDIR_WRITE;
60         else
61                 ipo->ddir = DDIR_READ;
62
63         list_add_tail(&ipo->list, &td->io_log_list);
64 }
65
66 static void handle_trace(struct thread_data *td, struct blk_io_trace *t)
67 {
68         int rw;
69
70         if ((t->action & 0xffff) != __BLK_TA_QUEUE)
71                 return;
72
73         rw = (t->action & BLK_TC_ACT(BLK_TC_WRITE)) != 0;
74         store_ipo(td, t->sector, t->bytes, rw);
75 }
76
77 int load_blktrace(struct thread_data *td, const char *filename)
78 {
79         struct blk_io_trace t;
80         int fd;
81
82         fd = open(filename, O_RDONLY);
83         if (fd < 0) {
84                 td_verror(td, errno, "open blktrace file");
85                 return 1;
86         }
87
88         do {
89                 int ret = read(fd, &t, sizeof(t));
90
91                 if (ret < 0) {
92                         td_verror(td, errno, "read blktrace file");
93                         return 1;
94                 } else if (!ret) {
95                         break;
96                 } else if (ret != sizeof(t)) {
97                         log_err("fio: short read on blktrace file\n");
98                         return 1;
99                 }
100
101                 if ((t.magic & 0xffffff00) != BLK_IO_TRACE_MAGIC) {
102                         log_err("fio: bad magic in blktrace data\n");
103                         return 1;
104                 }
105                 if ((t.magic & 0xff) != BLK_IO_TRACE_VERSION) {
106                         log_err("fio: bad blktrace version %d\n", t.magic & 0xff);
107                         return 1;
108                 }
109                 ret = discard_pdu(fd, &t);
110                 if (ret) {
111                         td_verror(td, ret, "blktrace lseek");
112                         return 1;
113                 }
114                 handle_trace(td, &t);
115         } while (1);
116
117         close(fd);
118         return 0;
119 }