Whamcloud - gitweb
LU-11270 mdt: better DOM data discard
[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>"
55                "-a <adjacent reads> [-v] [-h] [-C] [-l <stride_length> ] "
56                "[ -o <stride_offset> ] [-S <seed>] [-n <iterations>]"
57                "[-w <width>] [-t <timelimit>]\n");
58 }
59
60 enum {
61         BSIZE_DEFAULT = 16 * 4096
62 };
63
64 #define LOG(level, ...)                         \
65 ({                                              \
66         if ((level) <= verbosity)               \
67                 fprintf(stderr, __VA_ARGS__);   \
68 })
69
70 enum {
71         LOG_CRIT,
72         LOG_WARN,
73         LOG_INFO,
74         LOG_DEBUG
75 };
76
77 enum {
78         RR_OK,
79         RR_PARSE,
80         RR_SET,
81         RR_MALLOC,
82         RR_OPEN,
83         RR_PRECLEAN,
84         RR_READ
85 };
86
87 int main(int argc, char **argv)
88 {
89         int    verbosity = LOG_CRIT;
90         char  *fname = NULL;
91         loff_t size = 0;
92         size_t bsize = 0;
93         int    ad = 1;
94         int    preclean = 0;
95         int    width = 10;
96         unsigned int seed = 0;
97         unsigned long iterations = 0;
98         unsigned long timelimit = 24 * 3600;
99         unsigned long stride_length = 0;
100         unsigned long stride_offset = 0;
101
102         int opt;
103         int fd;
104         unsigned long nblocks;
105         unsigned long i;
106         ssize_t  ret;
107
108         struct timeval start;
109         struct timeval stop;
110
111         double usecs;
112
113         char *buf;
114         char *term;
115
116         do {
117                 opt = getopt(argc, argv, "f:s:b:va:hCS:n:t:l:o:w:");
118                 switch (opt) {
119                 case -1:
120                         break;
121                 default:
122                         LOG(LOG_CRIT, "Unable to parse command line.\n");
123                 case 'h':
124                         usage();
125                         return RR_PARSE;
126                 case 'v':
127                         verbosity ++;
128                         break;
129                 case 'f':
130                         fname = strdup(optarg);
131                         break;
132                 case 's':
133                         size = strtol(optarg, &term, 0);
134                         if (term == optarg) {
135                                 fprintf (stderr, "Can't parse size %s\n", optarg);
136                                 usage();
137                                 return RR_SET;
138                         }
139                         break;
140                 case 'b':
141                         bsize = strtol(optarg, &term, 0);
142                         if (term == optarg) {
143                                 fprintf (stderr, "Can't parse bsize %s\n", optarg);
144                                 usage();
145                                 return RR_SET;
146                         }
147                         break;
148                 case 'a':
149                         ad = (int)strtol(optarg, &term, 0);
150                         if (term == optarg) {
151                                 fprintf (stderr, "Can't parse ad %s\n", optarg);
152                                 usage();
153                                 return RR_SET;
154                         }
155                         break;
156                 case 'C':
157                         preclean = 1;
158                         break;
159                 case 'S':
160                         seed = strtol(optarg, &term, 0);
161                         if (term == optarg) {
162                                 fprintf (stderr, "Can't parse seed %s\n", 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", optarg);
171                                 usage();
172                                 return RR_SET;
173                         }
174                         break;
175
176                         break;
177                 case 't':
178                         timelimit = strtol(optarg, &term, 0);
179                         if (term == optarg) {
180                                 fprintf (stderr, "Can't parse seed %s\n", optarg);
181                                 usage();
182                                 return RR_SET;
183                         }
184                         break;
185                 case 'l':
186                         stride_length = strtol(optarg, &term, 0);
187                         if (term == optarg) {
188                                 fprintf (stderr, "Can't parse seed %s\n", optarg);
189                                 usage();
190                                 return RR_SET;
191                         }
192                         break;
193                 case 'o':
194                         stride_offset = strtol(optarg, &term, 0);
195                         if (term == optarg) {
196                                 fprintf (stderr, "Can't parse seed %s\n", optarg);
197                                 usage();
198                                 return RR_SET;
199                         }
200                         break;
201                 case 'w':
202                         width = (int)strtol(optarg, &term, 0);
203                         if (term == optarg) {
204                                 fprintf (stderr, "Can't parse seed %s\n", optarg);
205                                 usage();
206                                 return RR_SET;
207                         }
208                         break;
209                 }
210         } while (opt != -1);
211
212         if (fname == NULL || size == 0 || bsize == 0 || ad <= 0) {
213                 usage();
214                 return RR_SET;
215         }
216
217         bsize /= ad;
218         nblocks = size / bsize;
219         buf = malloc(bsize);
220         if (buf == NULL) {
221                 LOG(LOG_CRIT, "malloc(%lu) failure: %s\n", (long)bsize,
222                     strerror(errno));
223                 return RR_MALLOC;
224         }
225
226         fd = open(fname, (preclean ? O_RDWR : O_RDONLY) | O_CREAT, 0700);
227         if (fd == -1) {
228                 LOG(LOG_CRIT, "malloc(\"%s\") failure: %s\n", fname,
229                     strerror(errno));
230                 return RR_OPEN;
231         }
232         if (preclean) {
233                 loff_t towrite;
234                 size_t count;
235
236                 LOG(LOG_INFO, "precleaning");
237                 for (i = 0, towrite = size; towrite > 0; towrite -= ret) {
238                         count = bsize < towrite ? bsize : towrite;
239                         memset(buf, bsize, seed + i++);
240                         ret = write(fd, buf, count);
241                         if (ret < 0) {
242                                 LOG(LOG_CRIT, "write() failure: %s\n",
243                                     strerror(errno));
244                                 close(fd);
245                                 return RR_PRECLEAN;
246                         }
247                 }
248         }
249         if (seed != 0)
250                 srand(seed);
251         gettimeofday(&start, NULL);
252         timelimit += start.tv_sec;
253         for (i = 0; !iterations || i < iterations; i ++) {
254                 unsigned long block_nr;
255                 int j;
256
257                 if (stride_length) 
258                         block_nr = (unsigned long)(i*stride_length + 
259                                                    stride_offset) % nblocks;
260                 else
261                         block_nr = (unsigned long)((double)nblocks*rand()/
262                                                    (RAND_MAX+1.0));
263                 if (i % width == 0)
264                         LOG(LOG_INFO, "\n%9lu: ", i);
265                 LOG(LOG_INFO, "%7lu ", block_nr);
266                 for (j = 0; j < ad; j++) {
267                         ret = pread(fd, buf, bsize, (block_nr + j) * bsize);
268                         if (ret != bsize) {
269                                 LOG(LOG_CRIT,
270                                     "pread(...%zi, %li) got: %zi, %s\n", bsize,
271                                     block_nr * bsize, ret, strerror(errno));
272                                 close(fd);
273                                 return RR_READ;
274                         }
275                 }
276                 gettimeofday(&stop, NULL);
277                 if (stop.tv_sec > timelimit)
278                         break;
279         }
280         close(fd);
281         usecs = (stop.tv_sec - start.tv_sec) * 1000000. +
282                 stop.tv_usec - start.tv_usec;
283         printf("\n%fs, %gMB/s\n", usecs / 1000000.,
284                (double)bsize * ad * i / usecs);
285         return RR_OK;
286 }