Whamcloud - gitweb
LU-14739 quota: nodemap squashed root cannot bypass quota
[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", optarg);
132                                 usage();
133                                 return RR_SET;
134                         }
135                         break;
136                 case 'b':
137                         bsize = strtol(optarg, &term, 0);
138                         if (term == optarg) {
139                                 fprintf (stderr, "Can't parse bsize %s\n", optarg);
140                                 usage();
141                                 return RR_SET;
142                         }
143                         break;
144                 case 'a':
145                         ad = (int)strtol(optarg, &term, 0);
146                         if (term == optarg) {
147                                 fprintf (stderr, "Can't parse ad %s\n", optarg);
148                                 usage();
149                                 return RR_SET;
150                         }
151                         break;
152                 case 'C':
153                         preclean = 1;
154                         break;
155                 case 'S':
156                         seed = strtol(optarg, &term, 0);
157                         if (term == optarg) {
158                                 fprintf (stderr, "Can't parse seed %s\n", optarg);
159                                 usage();
160                                 return RR_SET;
161                         }
162                         break;
163                 case 'n':
164                         iterations = 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
172                         break;
173                 case 't':
174                         timelimit = strtol(optarg, &term, 0);
175                         if (term == optarg) {
176                                 fprintf (stderr, "Can't parse seed %s\n", optarg);
177                                 usage();
178                                 return RR_SET;
179                         }
180                         break;
181                 case 'l':
182                         stride_length = 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 'o':
190                         stride_offset = 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 'w':
198                         width = (int)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                 }
206         } while (opt != -1);
207
208         if (fname == NULL || size == 0 || bsize == 0 || ad <= 0) {
209                 usage();
210                 return RR_SET;
211         }
212
213         bsize /= ad;
214         nblocks = size / bsize;
215         buf = malloc(bsize);
216         if (buf == NULL) {
217                 LOG(LOG_CRIT, "malloc(%lu) failure: %s\n", (long)bsize,
218                     strerror(errno));
219                 return RR_MALLOC;
220         }
221
222         fd = open(fname, (preclean ? O_RDWR : O_RDONLY) | O_CREAT, 0700);
223         if (fd == -1) {
224                 LOG(LOG_CRIT, "malloc(\"%s\") failure: %s\n", fname,
225                     strerror(errno));
226                 return RR_OPEN;
227         }
228         if (preclean) {
229                 loff_t towrite;
230                 size_t count;
231
232                 LOG(LOG_INFO, "precleaning");
233                 for (i = 0, towrite = size; towrite > 0; towrite -= ret) {
234                         count = bsize < towrite ? bsize : towrite;
235                         memset(buf, bsize, seed + i++);
236                         ret = write(fd, buf, count);
237                         if (ret < 0) {
238                                 LOG(LOG_CRIT, "write() failure: %s\n",
239                                     strerror(errno));
240                                 close(fd);
241                                 return RR_PRECLEAN;
242                         }
243                 }
244         }
245         if (seed != 0)
246                 srand(seed);
247         gettimeofday(&start, NULL);
248         timelimit += start.tv_sec;
249         for (i = 0; !iterations || i < iterations; i ++) {
250                 unsigned long block_nr;
251                 int j;
252
253                 if (stride_length) 
254                         block_nr = (unsigned long)(i*stride_length + 
255                                                    stride_offset) % nblocks;
256                 else
257                         block_nr = (unsigned long)((double)nblocks*rand()/
258                                                    (RAND_MAX+1.0));
259                 if (i % width == 0)
260                         LOG(LOG_INFO, "\n%9lu: ", i);
261                 LOG(LOG_INFO, "%7lu ", block_nr);
262                 for (j = 0; j < ad; j++) {
263                         ret = pread(fd, buf, bsize, (block_nr + j) * bsize);
264                         if (ret != bsize) {
265                                 LOG(LOG_CRIT,
266                                     "pread(...%zi, %li) got: %zi, %s\n", bsize,
267                                     block_nr * bsize, ret, strerror(errno));
268                                 close(fd);
269                                 return RR_READ;
270                         }
271                 }
272                 gettimeofday(&stop, NULL);
273                 if (stop.tv_sec > timelimit)
274                         break;
275         }
276         close(fd);
277         usecs = (stop.tv_sec - start.tv_sec) * 1000000. +
278                 stop.tv_usec - start.tv_usec;
279         printf("\n%fs, %gMB/s\n", usecs / 1000000.,
280                (double)bsize * ad * i / usecs);
281         return RR_OK;
282 }