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