4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
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.
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).
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
23 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Use is subject to license terms.
27 * This file is part of Lustre, http://www.lustre.org/
29 * lustre/tests/reads.c
33 * Author: Nikita Danilov <nikita@clusterfs.com>
36 #define _XOPEN_SOURCE 500 /* for pread(2) */
46 #include <sys/types.h>
49 static void usage(void)
51 printf("reads: read random or stride chunks of a file.\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");
57 BSIZE_DEFAULT = 16 * 4096
60 #define LOG(level, ...) \
62 if ((level) <= verbosity) \
63 fprintf(stderr, __VA_ARGS__); \
83 int main(int argc, char **argv)
85 int verbosity = LOG_CRIT;
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;
100 unsigned long nblocks;
104 struct timeval start;
113 opt = getopt(argc, argv, "f:s:b:va:hCS:n:t:l:o:w:");
118 LOG(LOG_CRIT, "Unable to parse command line.\n");
126 fname = strdup(optarg);
129 size = strtol(optarg, &term, 0);
130 if (term == optarg) {
131 fprintf(stderr, "Can't parse size %s\n",
138 bsize = strtol(optarg, &term, 0);
139 if (term == optarg) {
140 fprintf(stderr, "Can't parse bsize %s\n",
147 ad = (int)strtol(optarg, &term, 0);
148 if (term == optarg) {
149 fprintf(stderr, "Can't parse ad %s\n",
159 seed = strtol(optarg, &term, 0);
160 if (term == optarg) {
161 fprintf(stderr, "Can't parse seed %s\n",
168 iterations = strtol(optarg, &term, 0);
169 if (term == optarg) {
170 fprintf(stderr, "Can't parse seed %s\n",
179 timelimit = strtol(optarg, &term, 0);
180 if (term == optarg) {
181 fprintf(stderr, "Can't parse seed %s\n",
188 stride_length = strtol(optarg, &term, 0);
189 if (term == optarg) {
190 fprintf(stderr, "Can't parse seed %s\n",
197 stride_offset = strtol(optarg, &term, 0);
198 if (term == optarg) {
199 fprintf(stderr, "Can't parse seed %s\n",
206 width = (int)strtol(optarg, &term, 0);
207 if (term == optarg) {
208 fprintf(stderr, "Can't parse seed %s\n",
217 if (fname == NULL || size == 0 || bsize == 0 || ad <= 0) {
223 nblocks = size / bsize;
226 LOG(LOG_CRIT, "malloc(%lu) failure: %s\n", (long)bsize,
231 fd = open(fname, (preclean ? O_RDWR : O_RDONLY) | O_CREAT, 0700);
233 LOG(LOG_CRIT, "malloc(\"%s\") failure: %s\n", fname,
241 LOG(LOG_INFO, "precleaning");
242 for (i = 0, towrite = size; towrite > 0; towrite -= ret) {
243 count = bsize < towrite ? bsize : towrite;
244 memset(buf, bsize, seed + i++);
245 ret = write(fd, buf, count);
247 LOG(LOG_CRIT, "write() failure: %s\n",
256 gettimeofday(&start, NULL);
257 timelimit += start.tv_sec;
258 for (i = 0; !iterations || i < iterations; i++) {
259 unsigned long block_nr;
263 block_nr = (unsigned long)(i*stride_length +
264 stride_offset) % nblocks;
266 block_nr = (unsigned long)((double)nblocks*rand()/
269 LOG(LOG_INFO, "\n%9lu: ", i);
270 LOG(LOG_INFO, "%7lu ", block_nr);
271 for (j = 0; j < ad; j++) {
272 ret = pread(fd, buf, bsize, (block_nr + j) * bsize);
275 "pread(...%zi, %li) got: %zi, %s\n", bsize,
276 block_nr * bsize, ret, strerror(errno));
281 gettimeofday(&stop, NULL);
282 if (stop.tv_sec > timelimit)
286 usecs = (stop.tv_sec - start.tv_sec) * 1000000. +
287 stop.tv_usec - start.tv_usec;
288 printf("\n%fs, %gMB/s\n", usecs / 1000000.,
289 (double)bsize * ad * i / usecs);