Whamcloud - gitweb
f23d0a8605a872c2473c9c02ada30b5789221079
[fs/lustre-release.git] / lustre / tests / mpi / cascading_rw.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  * GPL HEADER START
5  *
6  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 only,
10  * as published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * General Public License version 2 for more details (a copy is included
16  * in the LICENSE file that accompanied this code).
17  *
18  * You should have received a copy of the GNU General Public License
19  * version 2 along with this program; If not, see
20  * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
21  *
22  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
23  * CA 95054 USA or visit www.sun.com if you need additional information or
24  * have any questions.
25  *
26  * GPL HEADER END
27  */
28 /*
29  * Copyright  2008 Sun Microsystems, Inc. All rights reserved
30  * Use is subject to license terms.
31  */
32 /*
33  * This file is part of Lustre, http://www.lustre.org/
34  * Lustre is a trademark of Sun Microsystems, Inc.
35  *
36  * lustre/tests/mpi/cascading_rw.c
37  *
38  * Author: You Feng <youfeng@clusterfs.com>
39  */
40
41 #include <config.h>
42 #include <mpi.h>
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <string.h>
46 #include <sys/types.h>
47 #include <sys/stat.h>
48 #include <fcntl.h>
49 #include <unistd.h>
50 #include <sys/ioctl.h>
51 #include <getopt.h>
52 #include <errno.h>
53 #include "lp_utils.h"
54 #ifndef _IOWR
55 # include <ioctl.h>
56 #endif
57
58 #include <lustre/liblustreapi.h>
59
60 int rank = 0;
61 int size = 0;
62
63 char *testdir = NULL;
64
65 void rw_file(char *name, long stride, unsigned int seed)
66 {
67         char filename[MAX_FILENAME_LEN];
68         char path[MAX_FILENAME_LEN]; 
69         char errmsg[MAX_FILENAME_LEN+20];
70         char *buf, *o_buf;
71         struct lov_user_md lum = {0};
72         int fd, rc, i, bad = 0, root = 0;
73         long off;
74         long PAGE_SIZE = sysconf(_SC_PAGESIZE);
75
76         sprintf(filename, "%s/%s", testdir, name);
77
78         if (rank == 0) {
79                 remove_file_or_dir(filename);
80
81                 lum.lmm_magic = LOV_USER_MAGIC;
82                 lum.lmm_stripe_size = 0;
83                 lum.lmm_stripe_count = 0;
84                 lum.lmm_stripe_offset = -1;
85
86                 fd = open(filename, O_CREAT | O_RDWR | O_LOV_DELAY_CREATE,
87                           FILEMODE);
88                 if (fd == -1) {
89                         sprintf(errmsg, "open of file %s", filename);
90                         FAIL(errmsg);
91                 }
92
93                 rc = ioctl(fd, LL_IOC_LOV_SETSTRIPE, &lum);
94                 if (rc == -1) {
95                         sprintf(errmsg, "ioctl SETSTRIPE of file %s", filename);
96                         FAIL(errmsg);
97                 }
98
99                 if (close(fd) == -1) {
100                         sprintf(errmsg, "close of file %s", filename);
101                         FAIL(errmsg);
102                 }
103
104                 strncpy(path, filename, MAX_FILENAME_LEN);
105                 rc = llapi_file_get_stripe(path, &lum);
106                 if (rc == -1) {
107                         sprintf(errmsg, "get stripe of file %s", filename);
108                         FAIL(errmsg);
109                 }
110         }
111
112         MPI_Barrier(MPI_COMM_WORLD);
113
114         if (stride < 0) {
115                 if (rank == 0) {
116                         srandom(seed);
117                         while (stride < PAGE_SIZE/2) {
118                                 stride = random();
119                                 stride -= stride % 16;
120                                 if (stride < 0)
121                                         stride = -stride;
122                                 stride %= 2 * lum.lmm_stripe_size;
123                         }
124                 }
125
126                 MPI_Barrier(MPI_COMM_WORLD);
127
128                 MPI_Bcast(&stride, 1, MPI_LONG, root, MPI_COMM_WORLD);
129         }
130
131         MPI_Barrier(MPI_COMM_WORLD);
132
133         buf = (char *)malloc(stride);
134         if (buf == NULL) {
135                 sprintf(errmsg, "malloc of buf with size %ld", stride);
136                 FAIL(errmsg);
137         }
138
139         if (rank == 0) {
140                 fd = open(filename, O_RDWR);
141                 if (fd == -1) {
142                         sprintf(errmsg, "open of file %s", filename);
143                         FAIL(errmsg);
144                 }
145
146                 off = 0;
147                 fill_stride(buf, stride, 0, off);
148                 rc = write(fd, buf, stride);
149                 if (rc != stride) {
150                         sprintf(errmsg, "write of file %s return %d",
151                                 filename, rc);
152                         FAIL(errmsg);
153                 }
154                 off += stride;
155
156                 while (off < size * stride) {
157                         fill_stride(buf, stride, 0x8080808080808080ULL, off);
158                         rc = write(fd, buf, stride);
159                         if (rc != stride) {
160                                 sprintf(errmsg, "write of file %s return %d",
161                                         filename, rc);
162                                 FAIL(errmsg);
163                         }
164
165                         off += stride;
166                 }
167
168                 if (close(fd) == -1) {
169                         sprintf(errmsg, "close of file %s", filename);
170                         FAIL(errmsg);
171                 }
172         }
173
174         MPI_Barrier(MPI_COMM_WORLD);
175
176         o_buf = (char *)malloc(stride);
177         if (o_buf == NULL) {
178                 sprintf(errmsg, "malloc of o_buf with size %ld", stride);
179                 FAIL(errmsg);
180         }
181
182         fd = open(filename, O_RDWR);
183         if (fd == -1) {
184                 sprintf(errmsg, "open of file %s", filename);
185                 FAIL(errmsg);
186         }
187
188         off = 0;
189         for (i = 1; i < size; ++i) {
190                 if (rank == i) {
191                         rc = lseek(fd, off, SEEK_SET);
192                         if (rc != off) {
193                                 sprintf(errmsg, "lseek of file %s return %d",
194                                         filename, rc);
195                                 FAIL(errmsg);
196                         }
197
198                         rc = read(fd, buf, stride);
199                         if (rc != stride) {
200                                 if (rc > 0) {
201                                         fill_stride(o_buf, rc, i - 1, off);
202                                         dump_diff(o_buf, buf, rc, off);
203                                 }
204                                 sprintf(errmsg, "read of file %s return %d",
205                                         filename, rc);
206                                 FAIL(errmsg);
207                         }
208
209                         fill_stride(o_buf, stride, i - 1, off);
210                         if (memcmp(o_buf, buf, stride) != 0) {
211                                 dump_diff(o_buf, buf, stride, off);
212                                 errno = 0;
213                                 sprintf(errmsg, "Error: diff data read from %s",
214                                         filename);
215                                 FAIL(errmsg);
216                         }
217                 }
218
219                 off += stride;
220
221                 if (rank == i) {
222                         fill_stride(buf, stride, i, off);
223                         rc = write(fd, buf, stride);
224                         if (rc != stride) {
225                                 sprintf(errmsg, "write of file %s return %d",
226                                         filename, rc);
227                                 FAIL(errmsg);
228                         }
229                 }
230
231                 MPI_Barrier(MPI_COMM_WORLD);
232         }
233
234         if (close(fd) == -1) {
235                 sprintf(errmsg, "close of file %s", filename);
236                 FAIL(errmsg);
237         }
238
239         MPI_Barrier(MPI_COMM_WORLD);
240
241         if (rank == 0) {
242                 fd = open(filename, O_RDONLY);
243                 if (fd == -1) {
244                         sprintf(errmsg, "open of file %s", filename);
245                         FAIL(errmsg);
246                 }
247
248                 off = 0;
249                 for (i = 0; i < size; ++i) {
250                         rc = read(fd, buf, stride);
251                         if (rc != stride) {
252                                 if (rc > 0) {
253                                         fill_stride(o_buf, rc, i, off);
254                                         dump_diff(o_buf, buf, rc, off);
255                                 }
256                                 sprintf(errmsg, "read of file %s", filename);
257                                 FAIL(errmsg);
258                         }
259
260                         fill_stride(o_buf, stride, i, off);
261                         if (memcmp(o_buf, buf, stride) != 0) {
262                                 bad = 1;
263                                 dump_diff(o_buf, buf, stride, off);
264                         }
265                         off += stride;
266                 }
267                 if (bad == 1) {
268                         errno = 0;
269                         sprintf(errmsg, "Error: diff data read from %s", filename);
270                         FAIL(errmsg);
271                 }
272         }
273
274         MPI_Barrier(MPI_COMM_WORLD);
275         fprintf(stderr, "passed barrier 5\n");
276
277         free(buf);
278         free(o_buf);
279 }
280
281 void cascading_rw(long stride, unsigned int seed)
282 {
283         begin("setup");
284         end("setup");
285
286         begin("test");
287         rw_file("cascading_rw", stride, seed);
288         end("test");
289
290         begin("cleanup");
291         remove_file("cascading_rw");
292         end("cleanup");
293 }
294
295 void usage(char *proc)
296 {
297         int i;
298
299         if (rank == 0) {
300                 printf("Usage: %s [-h] -d <testdir> [-s \"1024\"]\n", proc);
301                 printf("           [-n \"13\"] [-e \"12345\"]\n"); 
302                 printf("           [-v] [-V #] [-g]\n");
303                 printf("\t-h: prints this help message\n");
304                 printf("\t-d: the directory in which the tests will run\n");
305                 printf("\t-s: process stride size\n");
306                 printf("\t-n: repeat test # times\n");
307                 printf("\t-n: random seed, used to re-create previous runs\n");
308                 printf("\t-v: increase the verbositly level by 1\n");
309                 printf("\t-V: select a specific verbosity level\n");
310                 printf("\t-g: debug mode\n");
311         }
312
313         MPI_Initialized(&i);
314         if (i) MPI_Finalize();
315         exit(0);
316 }
317
318 int main(int argc, char *argv[])
319 {
320         int i, iterations = 16;
321         char c;
322         long stride = -1;
323         unsigned int seed = 0;
324
325         /* Check for -h parameter before MPI_Init so the binary can be
326            called directly, without, for instance, mpirun */
327         for (i = 1; i < argc; ++i) {
328                 if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help"))
329                         usage(argv[0]);
330         }
331
332         MPI_Init(&argc, &argv);
333         MPI_Comm_rank(MPI_COMM_WORLD, &rank);
334         MPI_Comm_size(MPI_COMM_WORLD, &size);
335
336                 /* Parse command line options */
337         while (1) {
338                 c = getopt(argc, argv, "d:e:ghn:s:vV:");
339                 if (c == -1)
340                         break;
341
342                 switch (c) {
343                 case 'd':
344                         testdir = optarg;
345                         break;
346                 case 'e':
347                         seed = (unsigned int)atoi(optarg);
348                         break;
349                 case 'g':
350                         debug = 1;
351                         break;
352                 case 'h':
353                         usage(argv[0]);
354                         break;
355                 case 'n':
356                         iterations = atoi(optarg);
357                         break;
358                 case 's':
359                         stride = atol(optarg);
360                         break;
361                 case 'v':
362                         verbose += 1;
363                         break;
364                 case 'V':
365                         verbose = atoi(optarg);
366                         break;
367                 }
368         }
369
370         if (rank == 0)
371                 printf("%s is running with %d process(es) %s\n",
372                        argv[0], size, debug ? "in DEBUG mode" : "\b\b");
373
374         if (size < 2) {
375                 fprintf(stderr,
376                         "There should be at least 3 process to run the test!\n");
377                 MPI_Abort(MPI_COMM_WORLD, 2);
378         }
379
380         if (testdir == NULL && rank == 0) {
381                 fprintf(stderr, "Please specify a test directory! (\"%s -h\" for help)\n",
382                        argv[0]);
383                 MPI_Abort(MPI_COMM_WORLD, 2);
384         }
385
386         lp_gethostname();
387
388         for (i = 0; i < iterations; ++i) {
389                 if (rank == 0)
390                         printf("%s: Running test #%s(iter %d)\n",
391                                timestamp(), argv[0], i);
392
393                 cascading_rw(stride, seed);
394                 MPI_Barrier(MPI_COMM_WORLD);
395         }
396
397         if (rank == 0)
398                 printf("%s: All tests passed!\n", timestamp());
399         MPI_Finalize();
400         return 0;
401 }