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