Whamcloud - gitweb
LU-1934 ofd: implement precreate batching
[fs/lustre-release.git] / lustre / tests / mpi / write_disjoint.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.sun.com/software/products/lustre/docs/GPLv2.pdf
19  *
20  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
21  * CA 95054 USA or visit www.sun.com if you need additional information or
22  * have any questions.
23  *
24  * GPL HEADER END
25  */
26 /*
27  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
28  * Use is subject to license terms.
29  */
30 /*
31  * This file is part of Lustre, http://www.lustre.org/
32  * Lustre is a trademark of Sun Microsystems, Inc.
33  *
34  * lustre/tests/write_disjoint.c
35  *
36  * Each loop does 3 things:
37  *   - rank 0 truncates to 0
38  *   - all ranks agree on a random chunk size
39  *   - all ranks race to write their pattern to their chunk of the file
40  *   - rank 0 makes sure that the resulting file size is ranks * chunk size
41  *   - rank 0 makes sure that everyone's patterns went to the right place
42  *
43  * compile: mpicc -g -Wall -o write_disjoint write_disjoint.c
44  * run:     mpirun -np N -machlist <hostlist file> write_disjoint
45  *  or:     pdsh -w <N hosts> write_disjoint
46  *  or:     prun -n N [-N M] write_disjoint
47  */
48
49 #include <stdlib.h>
50 #include <stdio.h>
51 #include <sys/types.h>
52 #include <sys/stat.h>
53 #include <fcntl.h>
54 #include <string.h>
55 #include <errno.h>
56 #include <unistd.h>
57 #include <stdarg.h>
58 #include "mpi.h"
59
60 #define CHUNK_MAX_SIZE 123456
61
62 void rprintf(int rank, int loop, const char *fmt, ...)
63 {
64         va_list       ap;
65
66         printf("rank %d, loop %d: ", rank, loop);
67
68         va_start(ap, fmt);
69
70         vprintf(fmt, ap);
71
72         MPI_Abort(MPI_COMM_WORLD, -1); /* This will exit() according to man */
73 }
74
75 #define CHUNK_SIZE(n) chunk_size[(n) % 2]
76
77 int main (int argc, char *argv[]) {
78         int i, n, fd, c;
79         unsigned long chunk_size[2];
80         int rank, noProcessors, done;
81         int error;
82         off_t offset;
83         char **chunk_buf;
84         char *read_buf;
85         struct stat stat_buf;
86         ssize_t ret;
87         char *filename = "/mnt/lustre/write_disjoint";
88         int numloops = 1000;
89         int random = 0;
90
91         error = MPI_Init(&argc, &argv);
92         if (error != MPI_SUCCESS)
93                 rprintf(-1, -1, "MPI_Init failed: %d\n", error);
94         /* Parse command line options */
95         while ((c = getopt(argc, argv, "f:n:")) != EOF) {
96                 switch (c) {
97                 case 'f':
98                         filename = optarg;
99                         break;
100                 case 'n':
101                         numloops = strtoul(optarg, NULL, 0);
102                         break;
103                 }
104         }
105
106         MPI_Comm_size(MPI_COMM_WORLD, &noProcessors);
107         MPI_Comm_rank(MPI_COMM_WORLD, &rank);
108
109         chunk_buf = malloc(noProcessors * sizeof(chunk_buf[0]));
110         for (i=0; i < noProcessors; i++) {
111                 chunk_buf[i] = malloc(CHUNK_MAX_SIZE);
112                 memset(chunk_buf[i], 'A'+ i, CHUNK_MAX_SIZE);
113         }
114         read_buf = malloc(noProcessors * CHUNK_MAX_SIZE);
115
116         if (rank == 0) {
117                 fd = open(filename, O_WRONLY|O_CREAT|O_TRUNC, 0666);
118                 if (fd < 0)
119                         rprintf(rank, -1, "open() returned %s\n",
120                                 strerror(errno));
121         }
122         MPI_Barrier(MPI_COMM_WORLD);
123
124         fd = open(filename, O_RDWR);
125         if (fd < 0)
126                 rprintf(rank, -1, "open() returned %s\n", strerror(errno));
127
128         for (n = 0; n < numloops; n++) {
129                 /* reset the environment */
130                 if (rank == 0) {
131                         ret = truncate(filename, 0);
132                         if (ret != 0)
133                                 rprintf(rank, n, "truncate() returned %s\n",
134                                         strerror(errno) );
135                         random = rand();
136                 }
137                 MPI_Bcast(&random, 1, MPI_INT, 0, MPI_COMM_WORLD);
138                 CHUNK_SIZE(n) = random % CHUNK_MAX_SIZE;
139
140                 if (n % 1000 == 0 && rank == 0)
141                         printf("loop %d: chunk_size %lu\n", n, CHUNK_SIZE(n));
142
143                 if (stat(filename, &stat_buf) < 0)
144                         rprintf(rank, n, "error stating %s: %s\n",
145                                 filename, strerror(errno));
146
147                 if (stat_buf.st_size != 0)
148                         rprintf(rank, n, "filesize = %lu. "
149                                 "Should be zero after truncate\n",
150                                 stat_buf.st_size);
151
152                 MPI_Barrier(MPI_COMM_WORLD);
153
154                 /* Do the race */
155                 offset = rank * CHUNK_SIZE(n);
156                 lseek(fd, offset, SEEK_SET);
157
158                 done = 0;
159                 do {
160                         ret = write(fd, chunk_buf[rank] + done,
161                                     CHUNK_SIZE(n) - done);
162                         if (ret < 0 && errno != EINTR)
163                                 rprintf(rank, n, "write() returned %s\n",
164                                         strerror(errno));
165                         if (ret > 0)
166                                 done += ret;
167                 } while (done != CHUNK_SIZE(n));
168
169                 MPI_Barrier(MPI_COMM_WORLD);
170
171                 /* Check the result */
172                 if (stat(filename, &stat_buf) < 0)
173                         rprintf(rank, n, "error stating %s: %s\n",
174                                 filename, strerror(errno));
175
176                 if (stat_buf.st_size != CHUNK_SIZE(n) * noProcessors) {
177                         if (n > 0)
178                                 printf("loop %d: chunk_size %lu, "
179                                        "file size was %lu\n",
180                                        n - 1, CHUNK_SIZE(n - 1),
181                                        CHUNK_SIZE(n - 1) *noProcessors);
182                         rprintf(rank, n, "invalid file size %lu"
183                                 " instead of %lu = %lu * %u\n",
184                                 (unsigned long)stat_buf.st_size,
185                                 CHUNK_SIZE(n) * noProcessors,
186                                 CHUNK_SIZE(n), noProcessors);
187                 }
188
189                 if (rank == 0) {
190                         if (lseek(fd, 0, SEEK_SET) < 0)
191                                 rprintf(rank, n, "error seeking to 0: %s\n",
192                                         strerror(errno));
193
194                         done = 0;
195                         do {
196                                 ret = read(fd, read_buf + done,
197                                            CHUNK_SIZE(n) * noProcessors - done);
198                                 if (ret < 0)
199                                         rprintf(rank, n, "read returned %s\n",
200                                                 strerror(errno));
201
202                                 done += ret;
203                         } while (done != CHUNK_SIZE(n) * noProcessors);
204
205                         for (i = 0; i < noProcessors; i++) {
206                                 char command[4096];
207                                 int j;
208                                 
209                                 if (!memcmp(read_buf + (i * CHUNK_SIZE(n)),
210                                             chunk_buf[i], CHUNK_SIZE(n)))
211                                         continue;
212
213                                 /* print out previous chunk sizes */
214                                 if (n > 0)
215                                         printf("loop %d: chunk_size %lu\n",
216                                                n - 1, CHUNK_SIZE(n - 1));
217
218                                 printf("loop %d: chunk %d corrupted "
219                                        "with chunk_size %lu, page_size %d\n",
220                                        n, i, CHUNK_SIZE(n), getpagesize());
221                                 printf("ranks:\tpage boundry\tchunk boundry\t"
222                                        "page boundry\n");
223                                 for (j = 1 ; j < noProcessors; j++) {
224                                         int b = j * CHUNK_SIZE(n);
225                                         printf("%c -> %c:\t%d\t%d\t%d\n",
226                                                'A' + j - 1, 'A' + j,
227                                                b & ~(getpagesize()-1), b,
228                                                (b + getpagesize()) &
229                                                ~(getpagesize()-1));
230                                 }
231
232                                 sprintf(command, "od -Ad -a %s", filename);
233                                 ret = system(command);
234                                 rprintf(0, n, "data check error - exiting\n");
235                         }
236                 }
237                 MPI_Barrier(MPI_COMM_WORLD);
238         }
239
240         printf("Finished after %d loops\n", n);
241         MPI_Finalize();
242         return 0;
243 }