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