Whamcloud - gitweb
corrected an error made in setepall in test-framework.sh, which affects
[fs/lustre-release.git] / lustre / tests / random-reads.c
1 /*
2  * Lustre Random Reads test
3  *
4  * Copyright (c) 2005 Cluster File Systems, Inc.
5  *
6  * Author: Nikita Danilov <nikita@clusterfs.com>
7  *
8  * This file is part of Lustre, http://www.lustre.org.
9  *
10  * Lustre is free software; you can redistribute it and/or modify it under the
11  * terms of version 2 of the GNU General Public License as published by the
12  * Free Software Foundation.
13  *
14  * Lustre is distributed in the hope that it will be useful, but WITHOUT ANY
15  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
17  * details.
18  *
19  * You should have received a copy of the GNU General Public License along
20  * with Lustre; if not, write to the Free Software Foundation, Inc., 675 Mass
21  * Ave, Cambridge, MA 02139, USA.
22  */
23
24 #define _XOPEN_SOURCE 500 /* for pread(2) */
25
26 #include <errno.h>
27 #include <fcntl.h>
28 #include <ctype.h>
29 #include <unistd.h>
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <string.h>
33
34 #include <sys/types.h>
35 #include <sys/time.h>
36
37 long long atoll(const char *nptr);
38
39 static void usage(void)
40 {
41         printf("random-reads: read random chunks of a file.\n");
42         printf("Usage:\n\n");
43         printf("random-reads -f <filename> -s <filesize> -b <buffersize> -a <adjacent reads> [-v] [-h] [-C] [-S <seed>] [-n <iterations>] [-w <width>] [-t <timelimit>]\n");
44 }
45
46 enum {
47         BSIZE_DEFAULT = 16 * 4096
48 };
49
50 #define LOG(level, ...)                         \
51 ({                                              \
52         if ((level) <= verbosity)               \
53                 fprintf(stderr, __VA_ARGS__);   \
54 })
55
56 enum {
57         LOG_CRIT,
58         LOG_WARN,
59         LOG_INFO,
60         LOG_DEBUG
61 };
62
63 enum {
64         RR_OK,
65         RR_PARSE,
66         RR_SET,
67         RR_MALLOC,
68         RR_OPEN,
69         RR_PRECLEAN,
70         RR_READ
71 };
72
73 int main(int argc, char **argv)
74 {
75         int    verbosity = LOG_CRIT;
76         char  *fname = NULL;
77         loff_t size = 0;
78         size_t bsize = 0;
79         int    ad = 1;
80         int    preclean = 0;
81         int    width = 10;
82         unsigned int seed = 0;
83         unsigned long iterations = 0;
84         unsigned long timelimit = 24 * 3600;
85
86         int opt;
87         int fd;
88         unsigned long nblocks;
89         unsigned long i;
90         ssize_t  ret;
91
92         struct timeval start;
93         struct timeval stop;
94
95         double usecs;
96
97         char *buf;
98
99         do {
100                 opt = getopt(argc, argv, "f:s:b:va:hCS:n:t:w:");
101                 switch (opt) {
102                 case -1:
103                         break;
104                 default:
105                         LOG(LOG_CRIT, "Unable to parse command line.\n");
106                 case 'h':
107                         usage();
108                         return RR_PARSE;
109                 case 'v':
110                         verbosity ++;
111                         break;
112                 case 'f':
113                         fname = strdup(optarg);
114                         break;
115                 case 's':
116                         size = atoll(optarg);
117                         break;
118                 case 'b':
119                         bsize = atol(optarg);
120                         break;
121                 case 'a':
122                         ad = atoi(optarg);
123                         break;
124                 case 'C':
125                         preclean = 1;
126                         break;
127                 case 'S':
128                         seed = atol(optarg);
129                         break;
130                 case 'n':
131                         iterations = atoll(optarg);
132                         break;
133                 case 't':
134                         timelimit = atoll(optarg);
135                         break;
136                 case 'w':
137                         width = atoi(optarg);
138                         break;
139                 }
140         } while (opt != -1);
141
142         if (fname == NULL || size == 0 || bsize == 0 || ad <= 0) {
143                 usage();
144                 return RR_SET;
145         }
146
147         bsize /= ad;
148         nblocks = size / bsize;
149         buf = malloc(bsize);
150         if (buf == NULL) {
151                 LOG(LOG_CRIT, "malloc(%lu) failure: %s\n", (long)bsize,
152                     strerror(errno));
153                 return RR_MALLOC;
154         }
155
156         fd = open(fname, (preclean ? O_RDWR : O_RDONLY) | O_CREAT, 0700);
157         if (fd == -1) {
158                 LOG(LOG_CRIT, "malloc(\"%s\") failure: %s\n", fname,
159                     strerror(errno));
160                 return RR_OPEN;
161         }
162         if (preclean) {
163                 loff_t towrite;
164                 size_t count;
165
166                 LOG(LOG_INFO, "precleaning");
167                 for (i = 0, towrite = size; towrite > 0; towrite -= ret) {
168                         count = bsize < towrite ? bsize : towrite;
169                         memset(buf, bsize, seed + i++);
170                         ret = write(fd, buf, count);
171                         if (ret < 0) {
172                                 LOG(LOG_CRIT, "write() failure: %s\n",
173                                     strerror(errno));
174                                 return RR_PRECLEAN;
175                         }
176                 }
177         }
178         if (seed != 0)
179                 srand(seed);
180         gettimeofday(&start, NULL);
181         timelimit += start.tv_sec;
182         for (i = 0; !iterations || i < iterations; i ++) {
183                 unsigned long block_nr;
184                 int j;
185
186                 block_nr = (int) ((double)nblocks*rand()/(RAND_MAX+1.0));
187                 if (i % width == 0)
188                         LOG(LOG_INFO, "\n%9lu: ", i);
189                 LOG(LOG_INFO, "%7lu ", block_nr);
190                 for (j = 0; j < ad; j++) {
191                         ret = pread(fd, buf, bsize, (block_nr + j) * bsize);
192                         if (ret != bsize) {
193                                 LOG(LOG_CRIT,
194                                     "pread(...%zi, %li) got: %zi, %s\n", bsize,
195                                     block_nr * bsize, ret, strerror(errno));
196                                 return RR_READ;
197                         }
198                 }
199                 gettimeofday(&stop, NULL);
200                 if (stop.tv_sec > timelimit)
201                         break;
202         }
203         usecs = (stop.tv_sec - start.tv_sec) * 1000000. +
204                 stop.tv_usec - start.tv_usec;
205         printf("\n%fs, %gMB/s\n", usecs / 1000000.,
206                (double)bsize * ad * i / usecs);
207         return RR_OK;
208 }