Whamcloud - gitweb
LU-17662 osd-zfs: Support for ZFS 2.2.3
[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) 2014, 2017, Intel Corporation.
28  */
29 /*
30  * This file is part of Lustre, http://www.lustre.org/
31  *
32  * lustre/tests/rwv.c
33  */
34
35 #include <stdio.h>
36 #include <sys/types.h>
37 #include <sys/stat.h>
38 #include <sys/uio.h>
39 #include <sys/mman.h>
40 #include <fcntl.h>
41 #include <errno.h>
42 #include <stdlib.h>
43 #include <unistd.h>
44
45 #include <lustre/lustreapi.h>
46
47 #define ACT_NONE        0
48 #define ACT_READ        1
49 #define ACT_WRITE       2
50 #define ACT_SEEK        4
51 #define ACT_READHOLE    8
52 #define ACT_VERIFY      16
53 #define ACT_OUTPUT      32
54
55 static void usage(void)
56 {
57         printf("usage: rwv -f filename <-r|-w> [-a] [-z] [-d] [-v]");
58         printf(" [-s offset] [-o[outf]] -n iovcnt SIZE1 SIZE2 SIZE3...\n");
59         printf("-a  append IO (O_APPEND)\n");
60         printf("-r  file read (O_RDONLY)\n");
61         printf("-w  file write (O_WRONLY)\n");
62         printf("-D  open file with (O_DIRECT)\n");
63         printf("-s  set the start pos of the read/write test\n");
64         printf("-z  test for read hitting hole\n");
65         printf("-d  create flags (O_LOV_DELAY_CREATE)\n");
66         printf("-v  verify the data content of read\n");
67         printf("-o  write the file content of read to an optional file\n");
68 }
69
70 static int data_verify(struct iovec *iov, int iovcnt, char c)
71 {
72         int i;
73
74         for (i = 0; i < iovcnt; i++) {
75                 size_t count = iov[i].iov_len;
76                 char *s = iov[i].iov_base;
77
78                 for (; count > 0; ++s, count--) {
79                         if (*s != c) {
80                                 printf("Data mismatch %x: %x\n", *s, c);
81                                 return 1;
82                         }
83                 }
84         }
85         return 0;
86 }
87
88 int main(int argc, char **argv)
89 {
90         int c;
91         int fd;
92         int rc = 0;
93         int flags = 0;
94         int iovcnt = 0;
95         int act = ACT_NONE;
96         int out_fd = -1;
97         char pad = 0xba;
98         char *end;
99         char *fname = "FILE";
100         unsigned long len = 0;
101         struct iovec *iov;
102         off64_t offset = 0;
103
104         while ((c = getopt(argc, argv, "f:n:s:rwahvdDzo::")) != -1) {
105                 switch (c) {
106                 case 'f':
107                         fname = optarg;
108                         break;
109                 case 'n':
110                         iovcnt = strtoul(optarg, &end, 0);
111                         if (*end) {
112                                 printf("Bad iov count: %s\n", optarg);
113                                 return 1;
114                         }
115                         if (iovcnt > UIO_MAXIOV || iovcnt <= 0) {
116                                 printf("Wrong iov count\n");
117                                 return 1;
118                         }
119                         break;
120                 case 's':
121                         act |= ACT_SEEK;
122                         offset = strtoull(optarg, &end, 0);
123                         if (*end) {
124                                 printf("Bad seek offset: %s\n", optarg);
125                                 return 1;
126                         }
127                         break;
128                 case 'w':
129                         act |= ACT_WRITE;
130                         flags |= O_WRONLY | O_CREAT;
131                         break;
132                 case 'r':
133                         act |= ACT_READ;
134                         flags |= O_RDONLY;
135                         break;
136                 case 'a':
137                         flags |= O_APPEND;
138                         break;
139                 case 'd':
140                         flags |= O_LOV_DELAY_CREATE;
141                         break;
142                 case 'D':
143                         flags |= O_DIRECT;
144                         break;
145                 case 'z':
146                         pad = 0;
147                         act |= ACT_READHOLE;
148                         break;
149                 case 'v':
150                         act |= ACT_VERIFY;
151                         break;
152                 case 'o':
153                         act |= ACT_OUTPUT;
154                         if (optarg)
155                                 out_fd = open(optarg, O_WRONLY | O_CREAT, 0644);
156                         else
157                                 out_fd = fileno(stdout);
158                         break;
159                 case 'h':
160                         usage();
161                         break;
162                 }
163         }
164
165         if (act == ACT_NONE) {
166                 usage();
167                 return 1;
168         }
169
170         if ((act & ACT_READ) &&  (act & ACT_WRITE)) {
171                 printf("Read and write test should be exclusive\n");
172                 return 1;
173         }
174
175         if (act & ACT_OUTPUT && (!(act & ACT_READ) || out_fd < 0)) {
176                 printf("-o not in read mode or cannot open the output file");
177                 return 1;
178         }
179
180         if (argc - optind < iovcnt) {
181                 printf("Not enough parameters for iov size\n");
182                 return 1;
183         }
184
185         iov = (struct iovec *)malloc(iovcnt * sizeof(struct iovec));
186         if (!iov) {
187                 printf("No memory %s\n", strerror(errno));
188                 return 1;
189         }
190
191         for (c = 0; c < iovcnt; c++) {
192                 struct iovec *iv = &iov[c];
193
194                 iv->iov_len = strtoul(argv[optind++], &end, 0);
195                 if (*end) {
196                         printf("Error iov size\n");
197                         rc = 1;
198                         goto out;
199                 }
200                 iv->iov_base = mmap(NULL, iv->iov_len, PROT_READ | PROT_WRITE,
201                                     MAP_PRIVATE | MAP_ANON, 0, 0);
202                 if (iv->iov_base == MAP_FAILED) {
203                         printf("No memory %s\n", strerror(errno));
204                         rc = 1;
205                         goto out;
206                 }
207                 if (act & ACT_WRITE)
208                         memset(iv->iov_base, pad, iv->iov_len);
209                 len += iv->iov_len;
210         }
211
212         fd = open(fname, O_LARGEFILE | flags, 0644);
213         if (fd == -1) {
214                 printf("Cannot open %s:%s\n", fname, strerror(errno));
215                 return 1;
216         }
217
218         if ((act & ACT_SEEK) && (lseek64(fd, offset, SEEK_SET) < 0)) {
219                 printf("Cannot seek %s\n", strerror(errno));
220                 rc = 1;
221                 goto out;
222         }
223
224         if (act & ACT_WRITE) {
225                 rc = writev(fd, iov, iovcnt);
226                 if (rc != len) {
227                         printf("Write error: %s (rc = %d, len = %ld)\n",
228                                strerror(errno), rc, len);
229                         rc = 1;
230                         goto out;
231                 }
232         } else if (act & ACT_READ) {
233                 rc = readv(fd, iov, iovcnt);
234                 if (rc != len) {
235                         printf("Read error: %s rc = %d\n", strerror(errno), rc);
236                         rc = 1;
237                         goto out;
238                 }
239
240                 /* It should return zeroed buf if the read hits hole.*/
241                 if (((act & ACT_READHOLE) || (act & ACT_VERIFY)) &&
242                     data_verify(iov, iovcnt, pad)) {
243                         rc = 1;
244                         goto out;
245                 }
246
247                 if (act & ACT_OUTPUT) {
248                         rc = writev(out_fd, iov, iovcnt);
249                         if (rc != len) {
250                                 printf("write error: %s rc = %d\n",
251                                        strerror(errno), rc);
252                                 rc = 1;
253                                 goto out;
254                         }
255                 }
256         }
257
258         rc = 0;
259 out:
260         if (iov)
261                 free(iov);
262         if (out_fd >= 0)
263                 close(out_fd);
264         return rc;
265 }