Whamcloud - gitweb
6cbfcb5002957a8c70486097dd33026de4d56f7e
[fs/lustre-release.git] / lustre / tests / test_brw.c
1 #include <stdio.h>
2 #include <string.h>
3 #include <unistd.h>
4 #include <fcntl.h>
5 #include <stdlib.h>
6 #include <errno.h>
7 #include <sys/mman.h>
8 #include <sys/types.h>
9 #include <sys/stat.h>
10
11 // not correctly in the headers yet!!
12 //#define O_DIRECT 0
13 #ifndef O_DIRECT
14 #define O_DIRECT         040000 /* direct disk access hint */
15 #endif
16
17 #define CERROR(fmt, arg...) fprintf(stderr, fmt, ## arg)
18 #ifndef __u64
19 #define __u64 long long
20 #define cpu_to_le64(v) (v)
21 #define le64_to_cpu(v) (v)
22 #endif
23
24 #ifndef LPU64
25 #define LPU64 "%Lu"
26 #define LPX64 "%#Lx"
27 #endif
28
29 #define READ  1
30 #define WRITE 2
31
32 #define LPDS sizeof(__u64)
33 int page_debug_setup(void *addr, int len, __u64 off, __u64 id)
34 {
35         off = cpu_to_le64(off);
36         id = cpu_to_le64(id);
37         memcpy(addr, (char *)&off, LPDS);
38         memcpy(addr + LPDS, (char *)&id, LPDS);
39
40         addr += len - LPDS - LPDS;
41         memcpy(addr, (char *)&off, LPDS);
42         memcpy(addr + LPDS, (char *)&id, LPDS);
43
44         return 0;
45 }
46
47 int page_debug_check(char *who, void *addr, int size, __u64 off, __u64 id)
48 {
49         __u64 ne_off;
50         int err = 0;
51
52         ne_off = le64_to_cpu(off);
53         id = le64_to_cpu(id);
54         if (memcmp(addr, (char *)&ne_off, LPDS)) {
55                 CERROR("%s: for offset "LPU64" off: "LPX64" != "LPX64"\n",
56                        who, off, *(__u64 *)addr, ne_off);
57                 err = -EINVAL;
58         }
59         if (memcmp(addr + LPDS, (char *)&id, LPDS)) {
60                 CERROR("%s: for offset "LPU64" id: "LPX64" != "LPX64"\n",
61                        who, off, *(__u64 *)(addr + LPDS), id);
62                 err = -EINVAL;
63         }
64
65         addr += size - LPDS - LPDS;
66         if (memcmp(addr, (char *)&ne_off, LPDS)) {
67                 CERROR("%s: for offset "LPU64" end off: "LPX64" != "LPX64"\n",
68                        who, off, *(__u64 *)addr, ne_off);
69                 err = -EINVAL;
70         }
71         if (memcmp(addr + LPDS, (char *)&id, LPDS)) {
72                 CERROR("%s: for offset "LPU64" end id: "LPX64" != "LPX64"\n",
73                        who, off, *(__u64 *)(addr + LPDS), id);
74                 err = -EINVAL;
75         }
76
77         return err;
78 }
79 #undef LPDS
80
81 void usage(char *prog)
82 {
83         fprintf(stderr,
84                 "usage: %s file count [[d]{r|w|rw} [pages_per_vec [objid]]]\n",
85                 prog);
86         exit(1);
87 }
88
89 int main(int argc, char **argv)
90 {
91         int fd;
92         char *buf;
93         long long count, last, offset;
94         long pg_vec, len;
95         long long objid = 3;
96         struct stat st;
97         int flags = 0;
98         int cmd = 0;
99         char *end;
100         int rc;
101
102         if (argc < 3 || argc > 6)
103                 usage(argv[0]);
104
105         count = strtoull(argv[2], &end, 0);
106         if (*end) {
107                 fprintf(stderr, "%s: invalid count '%s'\n", argv[0], argv[2]);
108                 usage(argv[0]);
109         }
110         if (argc >= 4) {
111                 if (strchr(argv[3], 'r')) {
112                         cmd = READ;
113                         flags = O_RDONLY;
114                 }
115                 if (strchr(argv[3], 'w')) {
116                         cmd |= WRITE;
117                         flags = O_RDWR | O_CREAT;
118                 }
119                 if (strchr(argv[3], 'd')) {
120                         flags |= O_DIRECT;
121                 }
122                 if (!cmd)
123                         usage(argv[0]);
124         } else {
125                 cmd = READ | WRITE;
126                 flags = O_RDWR | O_CREAT | O_DIRECT;
127         }
128
129         if (argc >= 5) {
130                 pg_vec = strtoul(argv[4], &end, 0);
131                 if (*end) {
132                         fprintf(stderr, "%s: invalid pages_per_vec '%s'\n",
133                                 argv[0], argv[4]);
134                         usage(argv[0]);
135                 }
136         }
137
138         if (argc >= 6) {
139                 objid = strtoull(argv[5], &end, 0);
140                 if (*end) {
141                         fprintf(stderr, "%s: invalid objid '%s'\n",
142                                 argv[0], argv[5]);
143                         usage(argv[0]);
144                 }
145         }
146
147         printf("%s: %s on %s(objid "LPX64") for "LPU64"x%ld pages \n",
148                argv[0], flags & O_DIRECT ? "directio" : "i/o",
149                argv[1], objid, count, pg_vec);
150
151         fd = open(argv[1], flags | O_LARGEFILE);
152         if (fd == -1) {
153                 fprintf(stderr, "%s: cannot open %s:  %s\n", argv[0],
154                         argv[1], strerror(errno));
155                 return 3;
156         }
157
158         rc = fstat(fd, &st);
159         if (rc < 0) {
160                 fprintf(stderr, "%s: cannot stat %s: %s\n", argv[0],
161                         argv[1], strerror(errno));
162                 return 4;
163         }
164
165         len = pg_vec * st.st_blksize;
166         last = (long long)count * len;
167
168         buf = mmap(0, len, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, 0, 0);
169         if (!buf) {
170                 fprintf(stderr, "%s: no buffer memory %s\n",
171                         argv[0], strerror(errno));
172                 return 2;
173         }
174
175         for (offset = 0; offset < last && cmd & WRITE; offset += len) {
176                 int i;
177
178                 for (i = 0; i < len; i += st.st_blksize)
179                         page_debug_setup(buf + i, st.st_blksize, offset + i,
180                                          objid);
181
182                 rc = write(fd, buf, len);
183
184                 for (i = 0; i < len; i += st.st_blksize) {
185                         if (page_debug_check("write", buf + i, st.st_blksize,
186                                              offset + i, objid))
187                                 return 10;
188                 }
189
190                 if (rc != len) {
191                         fprintf(stderr, "%s: write error: %s, rc %d != %ld\n",
192                                 argv[0], strerror(errno), rc, len);
193                         return 4;
194                 }
195         }
196
197         if (lseek(fd, 0, SEEK_SET) != 0) {
198                 fprintf(stderr, "%s: cannot seek %s\n",
199                         argv[0], strerror(errno));
200                 return 5;
201         }
202
203         for (offset = 0; offset < last && cmd & READ; offset += len) {
204                 int i;
205
206                 rc = read(fd, buf, len);
207                 if (rc != len) {
208                         fprintf(stderr, "%s: read error: %s, rc %d != %ld\n",
209                                 argv[0], strerror(errno), rc, len);
210                         return 6;
211                 }
212
213                 for (i = 0; i < len; i += st.st_blksize) {
214                         if (page_debug_check("read", buf + i, st.st_blksize,
215                                              offset + i, objid))
216                                 return 11;
217                 }
218         }
219
220         return 0;
221 }