Whamcloud - gitweb
LU-14487 lustre: remove references to Sun Trademark.
[fs/lustre-release.git] / lustre / tests / mpi / cascading_rw.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) 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/mpi/cascading_rw.c
30  *
31  * Author: You Feng <youfeng@clusterfs.com>
32  */
33
34 #include <config.h>
35 #include <mpi.h>
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <sys/types.h>
40 #include <asm/types.h>
41 #include <sys/stat.h>
42 #include <fcntl.h>
43 #include <unistd.h>
44 #include <sys/ioctl.h>
45 #include <getopt.h>
46 #include <errno.h>
47
48 #include <lustre/lustreapi.h>
49 #include "lp_utils.h"
50 #ifndef _IOWR
51 # include <ioctl.h>
52 #endif
53
54
55 int rank = 0;
56 int size = 0;
57
58 char *testdir = NULL;
59
60 void rw_file(char *name, long stride, unsigned int seed)
61 {
62         char filename[MAX_FILENAME_LEN];
63         char *buf, *o_buf;
64         struct lov_user_md lum = {0};
65         int fd, rc, i, bad = 0, root = 0;
66         long off;
67         long page_size = sysconf(_SC_PAGESIZE);
68
69         sprintf(filename, "%s/%s", testdir, name);
70
71         if (rank == 0) {
72                 remove_file_or_dir(filename);
73
74                 lum.lmm_magic = LOV_USER_MAGIC;
75                 lum.lmm_stripe_size = 0;
76                 lum.lmm_stripe_count = 0;
77                 lum.lmm_stripe_offset = -1;
78
79                 fd = open(filename, O_CREAT | O_RDWR | O_LOV_DELAY_CREATE,
80                         FILEMODE);
81                 if (fd == -1)
82                         FAILF("open of file %s", filename);
83
84                 rc = ioctl(fd, LL_IOC_LOV_SETSTRIPE, &lum);
85                 if (rc == -1)
86                         FAILF("ioctl SETSTRIPE of file %s", filename);
87
88                 if (close(fd) == -1)
89                         FAILF("close of file %s", filename);
90         }
91
92         MPI_Barrier(MPI_COMM_WORLD);
93
94         if (stride < 0) {
95                 if (rank == 0) {
96                         srandom(seed);
97                         while (stride < page_size/2) {
98                                 stride = random();
99                                 stride -= stride % 16;
100                                 if (stride < 0)
101                                         stride = -stride;
102                                 stride %= 2 * lum.lmm_stripe_size;
103                         }
104                 }
105
106                 MPI_Barrier(MPI_COMM_WORLD);
107
108                 MPI_Bcast(&stride, 1, MPI_LONG, root, MPI_COMM_WORLD);
109         }
110
111         MPI_Barrier(MPI_COMM_WORLD);
112
113         buf = (char *)malloc(stride);
114         if (!buf)
115                 FAILF("malloc of buf with size %ld", stride);
116
117         if (rank == 0) {
118                 fd = open(filename, O_RDWR);
119                 if (fd == -1)
120                         FAILF("open of file %s", filename);
121
122                 off = 0;
123                 fill_stride(buf, stride, 0, off);
124                 rc = write(fd, buf, stride);
125                 if (rc != stride)
126                         FAILF("write of file %s return %d", filename, rc);
127
128                 off += stride;
129                 while (off < size * stride) {
130                         fill_stride(buf, stride, 0x8080808080808080ULL, off);
131                         rc = write(fd, buf, stride);
132                         if (rc != stride)
133                                 FAILF("write of file %s return %d",
134                                       filename, rc);
135                         off += stride;
136                 }
137
138                 if (close(fd) == -1)
139                         FAILF("close of file %s", filename);
140         }
141
142         MPI_Barrier(MPI_COMM_WORLD);
143
144         o_buf = (char *)malloc(stride);
145         if (!o_buf)
146                 FAILF("malloc of o_buf with size %ld", stride);
147
148         fd = open(filename, O_RDWR);
149         if (fd == -1)
150                 FAILF("open of file %s", filename);
151
152         off = 0;
153         for (i = 1; i < size; ++i) {
154                 if (rank == i) {
155                         rc = lseek(fd, off, SEEK_SET);
156                         if (rc != off)
157                                 FAILF("lseek of file %s return %d",
158                                       filename, rc);
159
160                         rc = read(fd, buf, stride);
161                         if (rc != stride) {
162                                 if (rc > 0) {
163                                         fill_stride(o_buf, rc, i - 1, off);
164                                         dump_diff(o_buf, buf, rc, off);
165                                 }
166                                 FAILF("read of file %s return %d",
167                                       filename, rc);
168                         }
169
170                         fill_stride(o_buf, stride, i - 1, off);
171                         if (memcmp(o_buf, buf, stride) != 0) {
172                                 dump_diff(o_buf, buf, stride, off);
173                                 errno = 0;
174                                 FAILF("Error: diff data read from %s",
175                                       filename);
176                         }
177                 }
178
179                 off += stride;
180
181                 if (rank == i) {
182                         fill_stride(buf, stride, i, off);
183                         rc = write(fd, buf, stride);
184                         if (rc != stride)
185                                 FAILF("write of file %s return %d",
186                                       filename, rc);
187                 }
188
189                 MPI_Barrier(MPI_COMM_WORLD);
190         }
191
192         if (close(fd) == -1)
193                 FAILF("close of file %s", filename);
194
195         MPI_Barrier(MPI_COMM_WORLD);
196
197         if (rank == 0) {
198                 fd = open(filename, O_RDONLY);
199                 if (fd == -1)
200                         FAILF("open of file %s", filename);
201
202                 off = 0;
203                 for (i = 0; i < size; ++i) {
204                         rc = read(fd, buf, stride);
205                         if (rc != stride) {
206                                 if (rc > 0) {
207                                         fill_stride(o_buf, rc, i, off);
208                                         dump_diff(o_buf, buf, rc, off);
209                                 }
210                                 FAILF("read of file %s", filename);
211                         }
212
213                         fill_stride(o_buf, stride, i, off);
214                         if (memcmp(o_buf, buf, stride) != 0) {
215                                 bad = 1;
216                                 dump_diff(o_buf, buf, stride, off);
217                         }
218                         off += stride;
219                 }
220                 if (bad == 1) {
221                         errno = 0;
222                         FAILF("Error: diff data read from %s", filename);
223                 }
224         }
225
226         MPI_Barrier(MPI_COMM_WORLD);
227         fprintf(stderr, "passed barrier 5\n");
228
229         free(buf);
230         free(o_buf);
231 }
232
233 void cascading_rw(long stride, unsigned int seed)
234 {
235         begin("setup");
236         end("setup");
237
238         begin("test");
239         rw_file("cascading_rw", stride, seed);
240         end("test");
241
242         begin("cleanup");
243         remove_file("cascading_rw");
244         end("cleanup");
245 }
246
247 void usage(char *proc)
248 {
249         int i;
250
251         if (rank == 0) {
252                 printf("Usage: %s [-h] -d <testdir> [-s \"1024\"]\n", proc);
253                 printf("           [-n \"13\"] [-e \"12345\"]\n");
254                 printf("           [-v] [-V #] [-g]\n");
255                 printf("\t-h: prints this help message\n");
256                 printf("\t-d: the directory in which the tests will run\n");
257                 printf("\t-s: process stride size\n");
258                 printf("\t-n: repeat test # times\n");
259                 printf("\t-n: random seed, used to re-create previous runs\n");
260                 printf("\t-v: increase the verbositly level by 1\n");
261                 printf("\t-V: select a specific verbosity level\n");
262                 printf("\t-g: debug mode\n");
263         }
264
265         MPI_Initialized(&i);
266         if (i)
267                 MPI_Finalize();
268         exit(0);
269 }
270
271 int main(int argc, char *argv[])
272 {
273         int i, iterations = 16, c;
274         long stride = -1;
275         unsigned int seed = 0;
276
277         /*
278          * Check for -h parameter before MPI_Init so the binary can be
279          * called directly, without, for instance, mpirun
280          */
281         for (i = 1; i < argc; ++i) {
282                 if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help"))
283                         usage(argv[0]);
284         }
285
286         MPI_Init(&argc, &argv);
287         MPI_Comm_rank(MPI_COMM_WORLD, &rank);
288         MPI_Comm_size(MPI_COMM_WORLD, &size);
289
290         /* Parse command line options */
291         while (1) {
292                 c = getopt(argc, argv, "d:e:ghn:s:vV:");
293                 if (c == -1)
294                         break;
295
296                 switch (c) {
297                 case 'd':
298                         testdir = optarg;
299                         break;
300                 case 'e':
301                         seed = (unsigned int)atoi(optarg);
302                         break;
303                 case 'g':
304                         debug = 1;
305                         break;
306                 case 'h':
307                         usage(argv[0]);
308                         break;
309                 case 'n':
310                         iterations = atoi(optarg);
311                         break;
312                 case 's':
313                         stride = atol(optarg);
314                         break;
315                 case 'v':
316                         verbose += 1;
317                         break;
318                 case 'V':
319                         verbose = atoi(optarg);
320                         break;
321                 }
322         }
323
324         if (rank == 0)
325                 printf("%s is running with %d process(es) %s\n",
326                        argv[0], size, debug ? "in DEBUG mode" : "\b\b");
327
328         if (size < 2) {
329                 fprintf(stderr,
330                         "There should be at least 3 process to run the test!\n");
331                 MPI_Abort(MPI_COMM_WORLD, 2);
332         }
333
334         if (testdir == NULL && rank == 0) {
335                 fprintf(stderr,
336                         "Please specify a test directory! (\"%s -h\" for help)\n",
337                         argv[0]);
338                 MPI_Abort(MPI_COMM_WORLD, 2);
339         }
340
341         lp_gethostname();
342
343         for (i = 0; i < iterations; ++i) {
344                 if (rank == 0)
345                         printf("%s: Running test #%s(iter %d)\n",
346                                timestamp(), argv[0], i);
347
348                 cascading_rw(stride, seed);
349                 MPI_Barrier(MPI_COMM_WORLD);
350         }
351
352         if (rank == 0)
353                 printf("%s: All tests passed!\n", timestamp());
354         MPI_Finalize();
355         return 0;
356 }