Whamcloud - gitweb
LU-1347 build: remove the vim/emacs modelines
[fs/lustre-release.git] / lustre / tests / rwv.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, write to the
18  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19  * Boston, MA 021110-1307, USA
20  *
21  * GPL HEADER END
22  */
23 /*
24  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
25  * Use is subject to license terms.
26  *
27  * Copyright (c) 2012, Whamcloud, Inc.
28  */
29 /*
30  * This file is part of Lustre, http://www.lustre.org/
31  * Lustre is a trademark of Sun Microsystems, Inc.
32  *
33  * lustre/tests/rwv.c
34  */
35
36 #include <stdio.h>
37 #include <sys/types.h>
38 #include <sys/stat.h>
39 #include <sys/uio.h>
40 #include <sys/mman.h>
41 #include <fcntl.h>
42 #include <errno.h>
43 #include <stdlib.h>
44 #include <unistd.h>
45
46 #include <liblustre.h>
47 #include <lnet/lnetctl.h>
48 #include <obd.h>
49 #include <lustre_lib.h>
50 #include <obd_lov.h>
51 #include <lustre/liblustreapi.h>
52
53 #define ACT_NONE        0
54 #define ACT_READ        1
55 #define ACT_WRITE       2
56 #define ACT_SEEK        4
57 #define ACT_READHOLE    8
58 #define ACT_VERIFY      16
59
60 void usage()
61 {
62         printf("usage: rwv -f filename <-r|-w> [-a] [-z] [-d] [-v]"
63                 "[-s offset] -n iovcnt SIZE1 SIZE2 SIZE3...\n");
64         printf("-a  append IO (O_APPEND)\n");
65         printf("-r  file read (O_RDONLY)\n");
66         printf("-w  file write (O_WRONLY)\n");
67         printf("-s  set the start pos of the read/write test\n");
68         printf("-z  test for read hitting hole\n");
69         printf("-d  create flags (O_LOV_DELAY_CREATE)\n");
70         printf("-v  verify the data content of read\n");
71 }
72
73 int data_verify(struct iovec *iov, int iovcnt, char c)
74 {
75         int i;
76
77         for (i = 0; i < iovcnt; i++) {
78                 size_t count = iov[i].iov_len;
79                 char *s = iov[i].iov_base;
80
81                 for (; count > 0; ++s, count--) {
82                         if (*s != c) {
83                                 printf("Data mismatch %x: %x\n", *s, c);
84                                 return 1;
85                         }
86                 }
87         }
88         return 0;
89 }
90
91 int main(int argc, char** argv)
92 {
93         int c;
94         int fd;
95         int rc = 0;
96         int flags = 0;
97         int iovcnt = 0;
98         int act = ACT_NONE;
99         char pad = 0xba;
100         char *end;
101         char *fname = "FILE";
102         unsigned long len = 0;
103         struct iovec *iov;
104         off64_t offset = 0;
105
106         while ((c = getopt(argc, argv, "f:n:s:rwahvdz")) != -1) {
107                 switch (c) {
108                 case 'f':
109                         fname = optarg;
110                         break;
111                 case 'n':
112                         iovcnt = strtoul(optarg, &end, 0);
113                         if (*end) {
114                                 printf("Bad iov count: %s\n", optarg);
115                                 return 1;
116                         }
117                         if (iovcnt > UIO_MAXIOV || iovcnt <= 0) {
118                                 printf("Wrong iov count\n");
119                                 return 1;
120                         }
121                         break;
122                 case 's':
123                         act |= ACT_SEEK;
124                         offset = strtoull(optarg, &end, 0);
125                         if (*end) {
126                                 printf("Bad seek offset: %s\n", optarg);
127                                 return 1;
128                         }
129                         break;
130                 case 'w':
131                         act |= ACT_WRITE;
132                         break;
133                 case 'r':
134                         act |= ACT_READ;
135                         break;
136                 case 'a':
137                         flags |= O_APPEND;
138                         break;
139                 case 'd':
140                         flags |= O_LOV_DELAY_CREATE;
141                         break;
142                 case 'z':
143                         pad = 0;
144                         act |= ACT_READHOLE;
145                         break;
146                 case 'v':
147                         act |= ACT_VERIFY;
148                         break;
149                 case 'h':
150                         usage();
151                         break;
152                 }
153         }
154
155         if (act == ACT_NONE) {
156                 usage();
157                 return 1;
158         }
159
160         if ((act & ACT_READ) &&  (act & ACT_WRITE)) {
161                 printf("Read and write test should be exclusive\n");
162                 return 1;
163         }
164
165         if (argc - optind < iovcnt) {
166                 printf("Not enough parameters for iov size\n");
167                 return 1;
168         }
169
170         iov = (struct iovec *)malloc(iovcnt * sizeof(struct iovec));
171         if (iov == NULL) {
172                 printf("No memory %s\n", strerror(errno));
173                 return 1;
174         }
175
176         for (c = 0; c < iovcnt; c++) {
177                 struct iovec *iv = &iov[c];
178
179                 iv->iov_len = strtoul(argv[optind++], &end, 0);
180                 if (*end) {
181                         printf("Error iov size\n");
182                         GOTO(out, rc = 1);
183                 }
184                 iv->iov_base = mmap(NULL, iv->iov_len, PROT_READ | PROT_WRITE,
185                                     MAP_PRIVATE | MAP_ANON, 0, 0);
186                 if (iv->iov_base == MAP_FAILED) {
187                         printf("No memory %s\n", strerror(errno));
188                         GOTO(out, rc = 1);
189                 }
190                 if (act & ACT_WRITE)
191                         memset(iv->iov_base, pad, iv->iov_len);
192                 len += iv->iov_len;
193         }
194
195         fd = open(fname, O_LARGEFILE | O_RDWR | O_CREAT | flags, 0644);
196         if (fd == -1) {
197                 printf("Cannot open %s:%s\n", fname, strerror(errno));
198                 return 1;
199         }
200
201         if ((act & ACT_SEEK) && (lseek64(fd, offset, SEEK_SET) < 0)) {
202                 printf("Cannot seek %s\n", strerror(errno));
203                 GOTO(out, rc == 1);
204         }
205
206         if (act & ACT_WRITE) {
207                 rc = writev(fd, iov, iovcnt);
208                 if (rc != len) {
209                         printf("Write error: %s (rc = %d, len = %ld)\n",
210                                 strerror(errno), rc, len);
211                         GOTO(out, rc = 1);
212                 }
213         } else if (act & ACT_READ) {
214                 rc = readv(fd, iov, iovcnt);
215                 if (rc != len) {
216                         printf("Read error: %s rc = %d\n", strerror(errno), rc);
217                         GOTO(out, rc = 1);
218                 }
219
220                 /* It should return zeroed buf if the read hits hole.*/
221                 if (((act & ACT_READHOLE) || (act & ACT_VERIFY)) &&
222                     data_verify(iov, iovcnt, pad))
223                         GOTO(out, rc = 1);
224         }
225
226         rc = 0;
227 out:
228         if (iov)
229                 free(iov);
230         return rc;
231 }