Whamcloud - gitweb
LU-17895 lnet: Validate input for lnetctl import
[fs/lustre-release.git] / lustre / tests / reads.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.gnu.org/licenses/gpl-2.0.html
19  *
20  * GPL HEADER END
21  */
22 /*
23  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
24  * Use is subject to license terms.
25  */
26 /*
27  * This file is part of Lustre, http://www.lustre.org/
28  *
29  * lustre/tests/reads.c
30  *
31  * Lustre Reads test
32  *
33  * Author: Nikita Danilov <nikita@clusterfs.com>
34  */
35
36 #define _XOPEN_SOURCE 500 /* for pread(2) */
37
38 #include <errno.h>
39 #include <fcntl.h>
40 #include <ctype.h>
41 #include <unistd.h>
42 #include <stdlib.h>
43 #include <stdio.h>
44 #include <string.h>
45
46 #include <sys/types.h>
47 #include <sys/time.h>
48
49 static void usage(void)
50 {
51         printf("reads: read random or stride chunks of a file.\n");
52         printf("Usage:\n\n");
53         printf("reads -f <filename> -s <filesize> -b <buffersize> -a <adjacent reads> [-v] [-h] [-C] [-l <stride_length> ] [ -o <stride_offset> ] [-S <seed>] [-n <iterations>][-w <width>] [-t <timelimit>]\n");
54 }
55
56 enum {
57         BSIZE_DEFAULT = 16 * 4096
58 };
59
60 #define LOG(level, ...)                         \
61 ({                                              \
62         if ((level) <= verbosity)               \
63                 fprintf(stderr, __VA_ARGS__);   \
64 })
65
66 enum {
67         LOG_CRIT,
68         LOG_WARN,
69         LOG_INFO,
70         LOG_DEBUG
71 };
72
73 enum {
74         RR_OK,
75         RR_PARSE,
76         RR_SET,
77         RR_MALLOC,
78         RR_OPEN,
79         RR_PRECLEAN,
80         RR_READ
81 };
82
83 int main(int argc, char **argv)
84 {
85         int    verbosity = LOG_CRIT;
86         char  *fname = NULL;
87         loff_t size = 0;
88         size_t bsize = 0;
89         int    ad = 1;
90         int    preclean = 0;
91         int    width = 10;
92         unsigned int seed = 0;
93         unsigned long iterations = 0;
94         unsigned long timelimit = 24 * 3600;
95         unsigned long stride_length = 0;
96         unsigned long stride_offset = 0;
97
98         int opt;
99         int fd;
100         unsigned long nblocks;
101         unsigned long i;
102         ssize_t  ret;
103
104         struct timeval start;
105         struct timeval stop;
106
107         double usecs;
108
109         char *buf;
110         char *term;
111
112         do {
113                 opt = getopt(argc, argv, "f:s:b:va:hCS:n:t:l:o:w:");
114                 switch (opt) {
115                 case -1:
116                         break;
117                 default:
118                         LOG(LOG_CRIT, "Unable to parse command line.\n");
119                 case 'h':
120                         usage();
121                         return RR_PARSE;
122                 case 'v':
123                         verbosity++;
124                         break;
125                 case 'f':
126                         fname = strdup(optarg);
127                         break;
128                 case 's':
129                         size = strtol(optarg, &term, 0);
130                         if (term == optarg) {
131                                 fprintf(stderr, "Can't parse size %s\n",
132                                         optarg);
133                                 usage();
134                                 return RR_SET;
135                         }
136                         break;
137                 case 'b':
138                         bsize = strtol(optarg, &term, 0);
139                         if (term == optarg) {
140                                 fprintf(stderr, "Can't parse bsize %s\n",
141                                         optarg);
142                                 usage();
143                                 return RR_SET;
144                         }
145                         break;
146                 case 'a':
147                         ad = (int)strtol(optarg, &term, 0);
148                         if (term == optarg) {
149                                 fprintf(stderr, "Can't parse ad %s\n",
150                                         optarg);
151                                 usage();
152                                 return RR_SET;
153                         }
154                         break;
155                 case 'C':
156                         preclean = 1;
157                         break;
158                 case 'S':
159                         seed = strtol(optarg, &term, 0);
160                         if (term == optarg) {
161                                 fprintf(stderr, "Can't parse seed %s\n",
162                                         optarg);
163                                 usage();
164                                 return RR_SET;
165                         }
166                         break;
167                 case 'n':
168                         iterations = strtol(optarg, &term, 0);
169                         if (term == optarg) {
170                                 fprintf(stderr, "Can't parse seed %s\n",
171                                         optarg);
172                                 usage();
173                                 return RR_SET;
174                         }
175                         break;
176
177                         break;
178                 case 't':
179                         timelimit = strtol(optarg, &term, 0);
180                         if (term == optarg) {
181                                 fprintf(stderr, "Can't parse seed %s\n",
182                                         optarg);
183                                 usage();
184                                 return RR_SET;
185                         }
186                         break;
187                 case 'l':
188                         stride_length = strtol(optarg, &term, 0);
189                         if (term == optarg) {
190                                 fprintf(stderr, "Can't parse seed %s\n",
191                                         optarg);
192                                 usage();
193                                 return RR_SET;
194                         }
195                         break;
196                 case 'o':
197                         stride_offset = strtol(optarg, &term, 0);
198                         if (term == optarg) {
199                                 fprintf(stderr, "Can't parse seed %s\n",
200                                         optarg);
201                                 usage();
202                                 return RR_SET;
203                         }
204                         break;
205                 case 'w':
206                         width = (int)strtol(optarg, &term, 0);
207                         if (term == optarg) {
208                                 fprintf(stderr, "Can't parse seed %s\n",
209                                         optarg);
210                                 usage();
211                                 return RR_SET;
212                         }
213                         break;
214                 }
215         } while (opt != -1);
216
217         if (fname == NULL || size == 0 || bsize == 0 || ad <= 0) {
218                 usage();
219                 return RR_SET;
220         }
221
222         bsize /= ad;
223         nblocks = size / bsize;
224         buf = malloc(bsize);
225         if (buf == NULL) {
226                 LOG(LOG_CRIT, "malloc(%lu) failure: %s\n", (long)bsize,
227                     strerror(errno));
228                 return RR_MALLOC;
229         }
230
231         fd = open(fname, (preclean ? O_RDWR : O_RDONLY) | O_CREAT, 0700);
232         if (fd == -1) {
233                 LOG(LOG_CRIT, "malloc(\"%s\") failure: %s\n", fname,
234                     strerror(errno));
235                 return RR_OPEN;
236         }
237         if (preclean) {
238                 loff_t towrite;
239                 size_t count;
240
241                 LOG(LOG_INFO, "precleaning");
242                 for (i = 0, towrite = size; towrite > 0; towrite -= ret) {
243                         count = bsize < towrite ? bsize : towrite;
244                         memset(buf, bsize, seed + i++);
245                         ret = write(fd, buf, count);
246                         if (ret < 0) {
247                                 LOG(LOG_CRIT, "write() failure: %s\n",
248                                     strerror(errno));
249                                 close(fd);
250                                 return RR_PRECLEAN;
251                         }
252                 }
253         }
254         if (seed != 0)
255                 srand(seed);
256         gettimeofday(&start, NULL);
257         timelimit += start.tv_sec;
258         for (i = 0; !iterations || i < iterations; i++) {
259                 unsigned long block_nr;
260                 int j;
261
262                 if (stride_length)
263                         block_nr = (unsigned long)(i*stride_length +
264                                                    stride_offset) % nblocks;
265                 else
266                         block_nr = (unsigned long)((double)nblocks*rand()/
267                                                    (RAND_MAX+1.0));
268                 if (i % width == 0)
269                         LOG(LOG_INFO, "\n%9lu: ", i);
270                 LOG(LOG_INFO, "%7lu ", block_nr);
271                 for (j = 0; j < ad; j++) {
272                         ret = pread(fd, buf, bsize, (block_nr + j) * bsize);
273                         if (ret != bsize) {
274                                 LOG(LOG_CRIT,
275                                     "pread(...%zi, %li) got: %zi, %s\n", bsize,
276                                     block_nr * bsize, ret, strerror(errno));
277                                 close(fd);
278                                 return RR_READ;
279                         }
280                 }
281                 gettimeofday(&stop, NULL);
282                 if (stop.tv_sec > timelimit)
283                         break;
284         }
285         close(fd);
286         usecs = (stop.tv_sec - start.tv_sec) * 1000000. +
287                 stop.tv_usec - start.tv_usec;
288         printf("\n%fs, %gMB/s\n", usecs / 1000000.,
289                (double)bsize * ad * i / usecs);
290         return RR_OK;
291 }