Whamcloud - gitweb
LU-6245 libcfs: remove types.h from userland code
[fs/lustre-release.git] / lustre / tests / test_brw.c
1 /*
2  * GPL HEADER START
3  *
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 only,
8  * as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License version 2 for more details (a copy is included
14  * in the LICENSE file that accompanied this code).
15  *
16  * You should have received a copy of the GNU General Public License
17  * version 2 along with this program; If not, see
18  * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
19  *
20  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
21  * CA 95054 USA or visit www.sun.com if you need additional information or
22  * have any questions.
23  *
24  * GPL HEADER END
25  */
26 /*
27  * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
28  * Use is subject to license terms.
29  *
30  * Copyright (c) 2014, Intel Corporation.
31  */
32 /*
33  * This file is part of Lustre, http://www.lustre.org/
34  * Lustre is a trademark of Sun Microsystems, Inc.
35  */
36
37 /* for O_DIRECT */
38 #ifndef _GNU_SOURCE
39 #define _GNU_SOURCE
40 #endif
41
42 #include <inttypes.h>
43 #include <stdio.h>
44 #include <string.h>
45 #include <unistd.h>
46 #include <fcntl.h>
47 #include <stdlib.h>
48 #include <errno.h>
49 #include <sys/mman.h>
50 #include <sys/types.h>
51 #include <sys/stat.h>
52 #include <linux/types.h>
53
54 #include <libcfs/byteorder.h>
55
56 #define READ  1
57 #define WRITE 2
58
59 #define LPDS sizeof(__u64)
60 int block_debug_setup(void *addr, int len, __u64 off, __u64 id)
61 {
62         off = cpu_to_le64(off);
63         id = cpu_to_le64(id);
64         memcpy(addr, (char *)&off, LPDS);
65         memcpy(addr + LPDS, (char *)&id, LPDS);
66
67         addr += len - LPDS - LPDS;
68         memcpy(addr, (char *)&off, LPDS);
69         memcpy(addr + LPDS, (char *)&id, LPDS);
70
71         return 0;
72 }
73
74 int block_debug_check(char *who, void *addr, int size, uint64_t off, uint64_t id)
75 {
76         uint64_t ne_off;
77         int err = 0;
78
79         ne_off = le64_to_cpu(off);
80         id = le64_to_cpu(id);
81         if (memcmp(addr, (char *)&ne_off, LPDS)) {
82                 fprintf(stderr, "%s: for offset %"PRIu64" off: %"PRIx64" != %"PRIx64"\n",
83                         who, off, *(uint64_t *)addr, ne_off);
84                 err = -EINVAL;
85         }
86         if (memcmp(addr + LPDS, (char *)&id, LPDS)) {
87                 fprintf(stderr, "%s: for offset %"PRIu64" id: %"PRIx64" != %"PRIx64"\n",
88                         who, off, *(uint64_t *)(addr + LPDS), id);
89                 err = -EINVAL;
90         }
91
92         addr += size - LPDS - LPDS;
93         if (memcmp(addr, (char *)&ne_off, LPDS)) {
94                 fprintf(stderr, "%s: for offset %"PRIu64" end off: %"PRIx64" != %"PRIx64"\n",
95                         who, off, *(uint64_t *)addr, ne_off);
96                 err = -EINVAL;
97         }
98         if (memcmp(addr + LPDS, (char *)&id, LPDS)) {
99                 fprintf(stderr, "%s: for offset %"PRIu64" end id: %"PRIx64" != %"PRIx64"\n",
100                         who, off, *(uint64_t *)(addr + LPDS), id);
101                 err = -EINVAL;
102         }
103
104         return err;
105 }
106 #undef LPDS
107
108 void usage(char *prog)
109 {
110         fprintf(stderr,
111                 "usage: %s file count [[d]{r|w|rw} [pages_per_vec [objid]]]\n",
112                 prog);
113         exit(1);
114 }
115
116 int main(int argc, char **argv)
117 {
118         int fd;
119         char *buf;
120         long long count, last, offset;
121         long pg_vec, len;
122         uint64_t objid;
123         struct stat st;
124         int flags = 0;
125         int cmd = 0;
126         char *end;
127         int rc;
128
129         if (argc < 3 || argc > 6)
130                 usage(argv[0]);
131
132         count = strtoull(argv[2], &end, 0);
133         if (*end) {
134                 fprintf(stderr, "%s: invalid count '%s'\n", argv[0], argv[2]);
135                 usage(argv[0]);
136         }
137         if (argc >= 4) {
138                 if (strchr(argv[3], 'r')) {
139                         cmd = READ;
140                         flags = O_RDONLY;
141                 }
142                 if (strchr(argv[3], 'w')) {
143                         cmd |= WRITE;
144                         flags = O_RDWR | O_CREAT;
145                 }
146                 if (strchr(argv[3], 'd')) {
147 #ifdef O_DIRECT
148                         flags |= O_DIRECT;
149 #else
150                         fprintf(stderr,
151                                 "%s: O_DIRECT not supported in this build\n",
152                                 argv[0]);
153                         exit(1);
154 #endif
155                 }
156                 if (!cmd)
157                         usage(argv[0]);
158         } else {
159                 cmd = READ | WRITE;
160                 flags = O_RDWR | O_CREAT;
161 #ifdef O_DIRECT
162                 flags |= O_DIRECT;
163 #else
164                 fprintf(stderr, "%s: warning: not setting O_DIRECT\n",
165                         argv[0]);
166 #endif
167         }
168
169         if (argc >= 5) {
170                 pg_vec = strtoul(argv[4], &end, 0);
171                 if (*end) {
172                         fprintf(stderr, "%s: invalid pages_per_vec '%s'\n",
173                                 argv[0], argv[4]);
174                         usage(argv[0]);
175                 }
176         } else {
177                 pg_vec = 16;
178         }
179
180         if (argc >= 6) {
181                 objid = strtoull(argv[5], &end, 0);
182                 if (*end) {
183                         fprintf(stderr, "%s: invalid objid '%s'\n",
184                                 argv[0], argv[5]);
185                         usage(argv[0]);
186                 }
187         } else {
188                 objid = 3;
189         }
190
191         printf("%s: %s on %s(objid %"PRIx64") for %llux%ld pages \n",
192                argv[0],
193 #ifdef O_DIRECT
194                flags & O_DIRECT ? "directio" : "i/o",
195 #else
196                "i/o",
197 #endif
198                argv[1], objid, count, pg_vec);
199
200         fd = open(argv[1], flags | O_LARGEFILE);
201         if (fd == -1) {
202                 fprintf(stderr, "%s: cannot open %s:  %s\n", argv[0],
203                         argv[1], strerror(errno));
204                 return 3;
205         }
206
207         rc = fstat(fd, &st);
208         if (rc < 0) {
209                 fprintf(stderr, "%s: cannot stat %s: %s\n", argv[0],
210                         argv[1], strerror(errno));
211                 return 4;
212         }
213
214         len = pg_vec * st.st_blksize;
215         last = (long long)count * len;
216
217         buf = mmap(0, len, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, 0, 0);
218         if (buf == MAP_FAILED) {
219                 fprintf(stderr, "%s: no buffer memory %s\n",
220                         argv[0], strerror(errno));
221                 return 2;
222         }
223
224         for (offset = 0; offset < last && cmd & WRITE; offset += len) {
225                 int i;
226
227                 for (i = 0; i < len; i += st.st_blksize)
228                         block_debug_setup(buf + i, st.st_blksize, 
229                                           offset + i, objid);
230
231                 rc = write(fd, buf, len);
232
233                 for (i = 0; i < len; i += st.st_blksize) {
234                         if (block_debug_check("write", buf + i, st.st_blksize,
235                                               offset + i, objid))
236                                 return 10;
237                 }
238
239                 if (rc != len) {
240                         fprintf(stderr, "%s: write error: %s, rc %d != %ld\n",
241                                 argv[0], strerror(errno), rc, len);
242                         return 4;
243                 }
244         }
245
246         if (lseek(fd, 0, SEEK_SET) != 0) {
247                 fprintf(stderr, "%s: cannot seek %s\n",
248                         argv[0], strerror(errno));
249                 return 5;
250         }
251
252         for (offset = 0; offset < last && cmd & READ; offset += len) {
253                 int i;
254
255                 rc = read(fd, buf, len);
256                 if (rc != len) {
257                         fprintf(stderr, "%s: read error: %s, rc %d != %ld\n",
258                                 argv[0], strerror(errno), rc, len);
259                         return 6;
260                 }
261
262                 for (i = 0; i < len; i += st.st_blksize) {
263                         if (block_debug_check("read", buf + i, st.st_blksize,
264                                               offset + i, objid))
265                                 return 11;
266                 }
267         }
268
269         return 0;
270 }