Whamcloud - gitweb
LU-12790 obdclass: print jobid error message properly
[fs/lustre-release.git] / lustre / tests / mpi / parallel_grouplock.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) 2004, 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  * Lustre is a trademark of Sun Microsystems, Inc.
29  *
30  * lustre/tests/parallel_grouplock.c
31  *
32  * Author: You Feng <youfeng@clusterfs.com>
33  */
34
35 #include <limits.h>
36 #include <mpi.h>
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40 #include <sys/types.h>
41 #include <asm/types.h>
42 #include <sys/stat.h>
43 #include <fcntl.h>
44 #include <sys/ioctl.h>
45 #include <unistd.h>
46 #include <time.h>
47 #include <errno.h>
48 #include "lp_utils.h"
49
50 #define LPGL_BUF_LEN 8192
51 #define LPGL_TEST_ITEMS 12
52
53 #define MIN_GLHOST 5
54
55 #define MAX_WAIT_TRIES            10
56 #define WAIT_TIME                  1  /* secs */
57 #define ONE_MB               1048576  /*   1 MB */
58 #define MIN_LGBUF_SIZE     536870912  /* 512 MB */
59 #define MAX_LGBUF_SIZE     536870912  /* 512 MB */
60 // #define MAX_LGBUF_SIZE    1073741824  /*   1 GB */
61
62 #define READ    1
63 #define WRITE   2
64 #define IOCTL   3
65 #define CLOSE   4
66
67 int rank;
68 int size;
69
70 char *testdir;
71 int only_test;
72
73 char buf[LPGL_BUF_LEN];
74 char *lgbuf;
75 int lgbuf_size;
76 char filename[MAX_FILENAME_LEN];
77 char errmsg[MAX_FILENAME_LEN + 96];
78
79 static void
80 alloc_lgbuf()
81 {
82         if (lgbuf)
83                 return;
84
85         lgbuf_size = MAX_LGBUF_SIZE;
86         for (; lgbuf_size >= MIN_LGBUF_SIZE; lgbuf_size -= ONE_MB)
87                 if ((lgbuf = (char *)malloc(lgbuf_size)) != NULL)
88                         return;
89
90         FAIL("malloc of large buffer failed.\n");
91 }
92
93 static inline void
94 read_buf(int fd)
95 {
96         int pos, rc;
97
98         rc = read(fd, buf, sizeof(buf));
99         if (rc == -1) {
100                 pos = lseek(fd, 0, SEEK_CUR);
101                 sprintf(errmsg,
102                         "read of file %s at pos %d for %zu bytes returned %d: (%d) %s.\n",
103                         filename, pos, sizeof(buf), rc, errno, strerror(errno));
104                 FAIL(errmsg);
105         } else if (rc != sizeof(buf)) {
106                 pos = lseek(fd, 0, SEEK_CUR);
107                 sprintf(errmsg,
108                         "read of file %s at pos %d for %zu bytes returned %d.\n",
109                         filename, pos, sizeof(buf), rc);
110                 FAIL(errmsg);
111         }
112 }
113
114 static inline void
115 write_buf(int fd, int index)
116 {
117         int pos = index * sizeof(buf);
118         int rc;
119
120         memset(buf, index, sizeof(buf));
121         lseek(fd, pos, SEEK_SET);
122         rc = write(fd, buf, sizeof(buf));
123         if (rc == -1) {
124                 sprintf(errmsg,
125                         "write of file %s at pos %d for %zu bytes returned %d: (%d) %s.\n",
126                         filename, pos, sizeof(buf), rc, errno, strerror(errno));
127                 FAIL(errmsg);
128         } else if (rc != sizeof(buf)) {
129                 sprintf(errmsg,
130                         "write of file %s at pos %d for %zu bytes returned %d.\n",
131                         filename, pos, sizeof(buf), rc);
132                 FAIL(errmsg);
133         }
134 }
135
136 /*
137  * task0 attempts GR(gid=1) -- granted immediately
138  * task1 attempts PR|PW -- blocked, goes on waiting list
139  * task2 attempts GR(gid=1) -> should be granted
140  * task2 writes to file and releases GR(gid=1)
141  * task0 waits for task2 to complete its processing
142  * task0 writes to file and releases GR(gid=1)
143  * task1 PR|PW should be granted and reads the file
144  */
145 void grouplock_test1(char *filename, int fd, int blocking_op, int unlock_op)
146 {
147         MPI_Request req1, req2;
148         int iter, flag1, flag2, temp1, temp2;
149         int i, rc, gid = 1;
150
151         if (rank == 0) {
152                 if ((rc = ioctl(fd, LL_IOC_GROUP_LOCK, gid)) == -1) {
153                         sprintf(errmsg,
154                                 "ioctl GROUP_LOCK of file %s: (%d) %s.\n",
155                                 filename, errno, strerror(errno));
156                         FAIL(errmsg);
157                 }
158         }
159
160         MPI_Barrier(MPI_COMM_WORLD);
161
162         switch (rank) {
163         case 1:
164                 if (blocking_op == WRITE) {
165                         write_buf(fd, rank);
166                         lseek(fd, 0, SEEK_SET);
167                 }
168
169                 for (i = 0; i <= 2; i++)
170                         read_buf(fd);
171
172                 MPI_Send(&gid, 1, MPI_INT, 0, 1, MPI_COMM_WORLD);
173                 break;
174         case 2:
175                 /* Wait for task1 to progress. This could be racey. */
176                 sleep(WAIT_TIME);
177
178                 if ((rc = ioctl(fd, LL_IOC_GROUP_LOCK, gid)) == -1) {
179                         sprintf(errmsg,
180                                 "ioctl GROUP_LOCK of file %s: (%d) %s.\n",
181                                 filename, errno, strerror(errno));
182                         FAIL(errmsg);
183                 }
184
185                 write_buf(fd, rank);
186
187                 if (unlock_op == CLOSE)
188                         rc = close(fd);
189                 else
190                         rc = ioctl(fd, LL_IOC_GROUP_UNLOCK, gid);
191
192                 if (rc == -1) {
193                         sprintf(errmsg,
194                                 "%s release GROUP_LOCK of file %s: (%d) %s.\n",
195                                 (unlock_op == CLOSE) ? "close" : "ioctl",
196                                 filename, errno, strerror(errno));
197                         FAIL(errmsg);
198                 }
199                 MPI_Send(&gid, 1, MPI_INT, 0, 1, MPI_COMM_WORLD);
200                 break;
201         case 0:
202                 /* PR|PW task will tell us when it completes */
203                 MPI_Irecv(&temp1, 1, MPI_INT, 1, 1, MPI_COMM_WORLD, &req1);
204                 /* 2nd locking task will tell us when it completes */
205                 MPI_Irecv(&temp2, 1, MPI_INT, 2, 1, MPI_COMM_WORLD, &req2);
206
207                 /* Wait for task2 to complete. */
208                 iter = MAX_WAIT_TRIES;
209                 do {
210                         iter--;
211                         if (!iter)
212                                 FAIL("2nd locking task is not progressing\n");
213
214                         sleep(WAIT_TIME);
215
216                         MPI_Test(&req1, &flag1, MPI_STATUS_IGNORE);
217                         if (flag1)
218                                 FAIL("PR|PW task progressed even though GROUP lock is held\n");
219
220                         MPI_Test(&req2, &flag2, MPI_STATUS_IGNORE);
221                 } while (!flag2);
222
223                 /* Make sure task1 is still waiting. */
224                 iter = MAX_WAIT_TRIES;
225                 do {
226                         iter--;
227                         sleep(WAIT_TIME);
228                         MPI_Test(&req1, &flag1, MPI_STATUS_IGNORE);
229                         if (flag1)
230                                 FAIL("PR|PW task progressed even though GROUP lock is held\n");
231                 } while (iter);
232
233                 write_buf(fd, rank);
234
235                 /* Now we need to release the lock */
236                 if ((rc = ioctl(fd, LL_IOC_GROUP_UNLOCK, gid)) == -1) {
237                         sprintf(errmsg,
238                                 "ioctl GROUP_UNLOCK of file %s: (%d) %s.\n",
239                                 filename, errno, strerror(errno));
240                         FAIL(errmsg);
241                 }
242
243                 /* Wait for task1 to complete. */
244                 iter = MAX_WAIT_TRIES;
245                 do {
246                         iter--;
247                         if (!iter) {
248                                 FAIL("PR|PW task is not progressing even though GROUP lock was released\n");
249                                 break;
250                         }
251                         sleep(WAIT_TIME);
252                         MPI_Test(&req1, &flag1, MPI_STATUS_IGNORE);
253                 } while (!flag1);
254
255                 break;
256         }
257 }
258
259 /*
260  * task0 attempts GR(gid=1) -- granted immediately
261  * task1 attempts GR(gid=2) -- blocked
262  * task2 attempts PR|PW -- blocked
263  * task3 attempts GR(gid=2) -- blocked
264  * task4 attempts GR(gid=1) -- should be granted
265  * task0,4 writes to file and releases GR(gid=1) --
266  *       this allows task2 & 3's GR locks to be granted; task4 remains blocked.
267  * task1 & 3 write to file and release GR(gid=2)
268  * task2 PR|PW should be granted and reads the file.
269  */
270 void grouplock_test2(char *filename, int fd, int blocking_op, int unlock_op)
271 {
272         int i, iter, rc, gid = 1;
273         int flag1, flag2, flag3, flag4;
274         int temp1, temp2, temp3, temp4;
275         MPI_Request req1, req2, req3, req4;
276
277         if (rank == 0) {
278                 if ((rc = ioctl(fd, LL_IOC_GROUP_LOCK, gid)) == -1) {
279                         sprintf(errmsg,
280                                 "ioctl GROUP_LOCK of file %s: (%d) %s.\n",
281                                 filename, errno, strerror(errno));
282                         FAIL(errmsg);
283                 }
284         }
285
286         MPI_Barrier(MPI_COMM_WORLD);
287
288         switch (rank) {
289         case 3:
290                 /* Wait for task2 to issue its read request. */
291                 sleep(2 * WAIT_TIME);
292         case 1:
293                 gid = 2;
294                 if ((rc = ioctl(fd, LL_IOC_GROUP_LOCK, gid)) == -1) {
295                         sprintf(errmsg,
296                                 "ioctl GROUP_LOCK of file %s: (%d) %s.\n",
297                                 filename, errno, strerror(errno));
298                         FAIL(errmsg);
299                 }
300
301                 write_buf(fd, rank);
302
303                 MPI_Send(&gid, 1, MPI_INT, 0, 1, MPI_COMM_WORLD);
304
305                 /*
306                  * Do not release the locks until task 0 is ready to watch
307                  * for reading task only
308                  */
309                 MPI_Recv(&temp1, 1, MPI_INT, 0, 1, MPI_COMM_WORLD,
310                          MPI_STATUS_IGNORE);
311
312                 if (unlock_op == CLOSE)
313                         rc = close(fd);
314                 else
315                         rc = ioctl(fd, LL_IOC_GROUP_UNLOCK, gid);
316                 if (rc == -1) {
317                         sprintf(errmsg,
318                                 "%s release GROUP_LOCK of file %s: (%d) %s.\n",
319                                 (unlock_op == CLOSE) ? "close" : "ioctl",
320                                 filename, errno, strerror(errno));
321                         FAIL(errmsg);
322                 }
323                 break;
324         case 2:
325                 /* Give task1 a chance to request its GR lock. */
326                 sleep(WAIT_TIME);
327
328                 if (blocking_op == WRITE) {
329                         write_buf(fd, rank);
330                         lseek(fd, 0, SEEK_SET);
331                 }
332
333                 for (i = 0; i <= 3; i++)
334                         read_buf(fd);
335
336                 MPI_Send(&gid, 1, MPI_INT, 0, 1, MPI_COMM_WORLD);
337                 break;
338         case 4:
339                 /* Give task1 & 3 a chance to queue their GR locks. */
340                 sleep(3 * WAIT_TIME);
341
342                 if ((rc = ioctl(fd, LL_IOC_GROUP_LOCK, gid)) == -1) {
343                         sprintf(errmsg,
344                                 "ioctl GROUP_LOCK of file %s: (%d) %s.\n",
345                                 filename, errno, strerror(errno));
346                         FAIL(errmsg);
347                 }
348
349                 write_buf(fd, rank);
350
351                 rc = ioctl(fd, LL_IOC_GROUP_UNLOCK, gid);
352                 if (rc == -1) {
353                         sprintf(errmsg,
354                                 "%s release GROUP_LOCK of file %s: (%d) %s.\n",
355                                 (unlock_op == CLOSE) ? "close" : "ioctl",
356                                 filename, errno, strerror(errno));
357                         FAIL(errmsg);
358                 }
359
360                 MPI_Send(&gid, 1, MPI_INT, 0, 1, MPI_COMM_WORLD);
361                 break;
362         case 0:
363                 /* locking tasks will tell us when they complete */
364                 MPI_Irecv(&temp1, 1, MPI_INT, 1, 1, MPI_COMM_WORLD, &req1);
365                 MPI_Irecv(&temp2, 1, MPI_INT, 2, 1, MPI_COMM_WORLD, &req2);
366                 MPI_Irecv(&temp3, 1, MPI_INT, 3, 1, MPI_COMM_WORLD, &req3);
367                 MPI_Irecv(&temp4, 1, MPI_INT, 4, 1, MPI_COMM_WORLD, &req4);
368
369                 /* Make sure all tasks that should be blocked are waiting. */
370                 iter = MAX_WAIT_TRIES;
371                 do {
372                         iter--;
373                         sleep(WAIT_TIME);
374                         MPI_Test(&req1, &flag1, MPI_STATUS_IGNORE);
375                         MPI_Test(&req2, &flag2, MPI_STATUS_IGNORE);
376                         MPI_Test(&req3, &flag3, MPI_STATUS_IGNORE);
377                         if (flag1 || flag3)
378                                 FAIL("GROUP (gid=2) task progressed even though GROUP (gid=1) lock is held.\n");
379                         if (flag2)
380                                 FAIL("PR|PW task progressed even though GROUP (gid=1) lock is still held\n");
381                 } while (iter);
382
383                 /* Wait for task4 to signal it has completed. */
384                 iter = MAX_WAIT_TRIES;
385                 do {
386                         iter--;
387                         if (!iter)
388                                 FAIL("2nd task GROUP(gid=1) not progressing\n");
389
390                         sleep(WAIT_TIME);
391                         MPI_Test(&req1, &flag1, MPI_STATUS_IGNORE);
392                         MPI_Test(&req2, &flag2, MPI_STATUS_IGNORE);
393                         MPI_Test(&req3, &flag3, MPI_STATUS_IGNORE);
394                         MPI_Test(&req4, &flag4, MPI_STATUS_IGNORE);
395                         if (flag1 || flag3)
396                                 FAIL("GROUP (gid=2) task progressed even though GROUP (gid=1) lock is held.\n");
397                         if (flag2)
398                                 FAIL("PR|PW task progressed even though GROUP (gid=1) lock is still held\n");
399                 } while (!flag4);
400
401                 write_buf(fd, rank);
402
403                 /* Now let's release first lock */
404                 if ((rc = ioctl(fd, LL_IOC_GROUP_UNLOCK, gid)) == -1) {
405                         sprintf(errmsg,
406                                 "ioctl GROUP_UNLOCK of file %s returned %d",
407                                 filename, rc);
408                         FAIL(errmsg);
409                 }
410
411                 /* Wait for task1 & 3 to signal they have their lock. */
412                 iter = MAX_WAIT_TRIES;
413                 do {
414                         iter--;
415                         if (!iter)
416                                 FAIL("GROUP(gid=2) tasks not progressing\n");
417
418                         sleep(WAIT_TIME);
419                         MPI_Test(&req1, &flag1, MPI_STATUS_IGNORE);
420                         MPI_Test(&req2, &flag2, MPI_STATUS_IGNORE);
421                         MPI_Test(&req3, &flag3, MPI_STATUS_IGNORE);
422                         if (flag2) {
423                                 fprintf(stderr, "task2 %d\n", flag2);
424                                 FAIL("PR task progressed even though GROUP lock was on the queue task\n");
425                         }
426                 } while (!(flag1 && flag3));
427
428                 /* Make sure task2 is still waiting. */
429                 iter = MAX_WAIT_TRIES;
430                 do {
431                         iter--;
432                         sleep(WAIT_TIME);
433                         MPI_Test(&req2, &flag2, MPI_STATUS_IGNORE);
434                         if (flag2)
435                                 FAIL("PR task progressed even though GR(gid=2) lock was active.\n");
436                 } while (iter);
437
438                 /* Tell task1 & 3 to release their GR(gid=2) lock. */
439                 MPI_Send(&gid, 1, MPI_INT, 1, 1, MPI_COMM_WORLD);
440                 MPI_Send(&gid, 1, MPI_INT, 3, 1, MPI_COMM_WORLD);
441
442                 /* Wait for task2 (PR) to complete. */
443                 iter = MAX_WAIT_TRIES;
444                 do {
445                         iter--;
446                         if (!iter) {
447                                 FAIL("reading task is not progressing even though GROUP locks are released\n");
448                                 break;
449                         }
450                         sleep(WAIT_TIME);
451                         MPI_Test(&req2, &flag2, MPI_STATUS_IGNORE);
452                 } while (!flag3);
453                 break;
454         }
455 }
456
457 /*
458  * Tests a bug that once existed in the group lock code;
459  * i.e. that a GR lock request on a O_NONBLOCK fd could fail even though
460  * there is no blocking GROUP lock ahead of it on the waitq.
461  *
462  * task0 starts a large write (PW). this test could be racey if this
463  *       write finishes too quickly.
464  * task1 attempts GR(gid=1) -- blocked
465  * task2 attempts GR(gid=2) with a O_NONBLOCK fs. should not fail.
466  */
467 void grouplock_test3(char *filename, int fd)
468 {
469         MPI_Request req1, req2;
470         int iter, flag1, flag2, temp1, temp2;
471         int rc, gid = 1;
472
473         if (rank == 0) {
474                 alloc_lgbuf();
475         } else if (rank == 2) {
476                 rc = fcntl(fd, F_SETFL, O_NONBLOCK);
477                 if (rc == -1) {
478                         sprintf(errmsg, "fcntl(O_NONBLOCK) failed: (%d) %s.\n",
479                                 errno, strerror(errno));
480                         FAIL(errmsg);
481                 }
482         }
483
484         MPI_Barrier(MPI_COMM_WORLD);
485
486         switch (rank) {
487         case 2:
488                 gid = 2;
489                 usleep(10000);
490                 usleep(10000);
491         case 1:
492                 /*
493                  * Racey, we have to sleep just long enough for
494                  * task0's write to start.
495                  */
496                 usleep(10000);
497
498                 if ((rc = ioctl(fd, LL_IOC_GROUP_LOCK, gid)) == -1) {
499                         sprintf(errmsg,
500                                 "ioctl GROUP_LOCK of file %s: (%d) %s.\n",
501                                 filename, errno, strerror(errno));
502                         FAIL(errmsg);
503                 }
504
505                 /* tell task0 we have the lock. */
506                 MPI_Send(&gid, 1, MPI_INT, 0, 1, MPI_COMM_WORLD);
507
508                 /* the close of fd will release the lock. */
509                 break;
510         case 0:
511                 rc = write(fd, lgbuf, lgbuf_size);
512                 if (rc == -1) {
513                         sprintf(errmsg,
514                                 "write of file %s for %d bytes returned %d: (%d) %s.\n",
515                                 filename, lgbuf_size,
516                                 rc, errno, strerror(errno));
517                         FAIL(errmsg);
518                 } else if (rc != lgbuf_size) {
519                         sprintf(errmsg,
520                                 "write of file %s for %d bytes returned %d.\n",
521                                 filename, lgbuf_size, rc);
522                         FAIL(errmsg);
523                 }
524
525                 /* GR tasks will tell us when they complete */
526                 MPI_Irecv(&temp1, 1, MPI_INT, 1, 1, MPI_COMM_WORLD, &req1);
527                 MPI_Irecv(&temp2, 1, MPI_INT, 2, 1, MPI_COMM_WORLD, &req2);
528
529                 /* Wait for task1 & 2 to complete. */
530                 iter = MAX_WAIT_TRIES;
531                 do {
532                         iter--;
533                         if (!iter) {
534                                 FAIL("GR(gid=1) tasks are not progressing even no conflicting locks exist.\n");
535                                 break;
536                         }
537                         sleep(WAIT_TIME);
538                         MPI_Test(&req1, &flag1, MPI_STATUS_IGNORE);
539                         MPI_Test(&req2, &flag2, MPI_STATUS_IGNORE);
540                 } while (!(flag1 && flag2));
541                 break;
542         }
543 }
544
545 /*
546  * Tests a bug that once existed in the group lock code;
547  * i.e. extent locks without O_NONBLOCK that go on the waitq before a group
548  * lock request came in and was granted. The extent lock would timed out and
549  * produce an error.
550  *
551  * task0 starts a large write (PW). this test could be racey if this
552  *       write finishes too quickly.
553  * task1 attempts PR -- blocked
554  * task2 attempts GR(gid=1) -- blocked
555  * task0 completes write
556  * task1 should wakeup and complete its read
557  * task2 should wakeup and after task1 complete.
558  */
559 void grouplock_test4(char *filename, int fd)
560 {
561         MPI_Request req1;
562         int iter, flag1, temp1;
563         int rc, gid = 1;
564
565         if (rank == 0)
566                 alloc_lgbuf();
567
568         MPI_Barrier(MPI_COMM_WORLD);
569
570         switch (rank) {
571         case 1:
572                 /*
573                  * Racey, we have to sleep just long enough for
574                  * task0's write to start.
575                  */
576                 MPI_Recv(&temp1, 1, MPI_INT, 0, 1, MPI_COMM_WORLD,
577                          MPI_STATUS_IGNORE);
578
579                 /* tell task2 to go. */
580                 MPI_Send(&gid, 1, MPI_INT, 2, 1, MPI_COMM_WORLD);
581                 sleep(WAIT_TIME);
582
583                 read_buf(fd);
584                 MPI_Send(&gid, 1, MPI_INT, 0, 1, MPI_COMM_WORLD);
585                 break;
586         case 2:
587                 /* Give task0 & 1 a chance to start. */
588                 MPI_Recv(&temp1, 1, MPI_INT, 1, 1, MPI_COMM_WORLD,
589                          MPI_STATUS_IGNORE);
590                 sleep(2 * WAIT_TIME);
591
592                 if ((rc = ioctl(fd, LL_IOC_GROUP_LOCK, gid)) == -1) {
593                         sprintf(errmsg,
594                                 "ioctl GROUP_LOCK of file %s: (%d) %s.\n",
595                                 filename, errno, strerror(errno));
596                         FAIL(errmsg);
597                 }
598
599                 /* tell task0 we have the lock. */
600                 MPI_Send(&gid, 1, MPI_INT, 0, 1, MPI_COMM_WORLD);
601
602                 /*
603                  * Do not release the locks until task 0 tells us too.
604                  * for reading task only
605                  */
606                 MPI_Recv(&temp1, 1, MPI_INT, 0, 1, MPI_COMM_WORLD,
607                          MPI_STATUS_IGNORE);
608
609                 rc = ioctl(fd, LL_IOC_GROUP_UNLOCK, gid);
610                 if (rc == -1) {
611                         sprintf(errmsg,
612                                 "ioctl GROUP_UNLOCK of file %s: (%d) %s.\n",
613                                 filename, errno, strerror(errno));
614                         FAIL(errmsg);
615                 }
616                 break;
617         case 0:
618                 /* tell task1 to go to avoid race */
619                 MPI_Send(&gid, 1, MPI_INT, 1, 1, MPI_COMM_WORLD);
620                 rc = write(fd, lgbuf, lgbuf_size);
621                 if (rc == -1) {
622                         sprintf(errmsg,
623                                 "write of file %s for %d bytes returned %d: (%d) %s.\n",
624                                 filename, lgbuf_size,
625                                 rc, errno, strerror(errno));
626                         FAIL(errmsg);
627                 } else if (rc != lgbuf_size) {
628                         sprintf(errmsg,
629                                 "write of file %s for %d bytes returned %d.\n",
630                                 filename, lgbuf_size, rc);
631                         FAIL(errmsg);
632                 }
633
634                 /* wait for task2 to get its lock. */
635                 MPI_Recv(&temp1, 1, MPI_INT, 2, 1, MPI_COMM_WORLD,
636                          MPI_STATUS_IGNORE);
637
638                 /* Tell task2 it's ok to release its GR(gid=1) lock. */
639                 MPI_Send(&gid, 1, MPI_INT, 2, 1, MPI_COMM_WORLD);
640
641                 /* wait a really long time. */
642                 sleep(180 * WAIT_TIME);
643
644                 /* PR task will tell us when it completes */
645                 MPI_Irecv(&temp1, 1, MPI_INT, 1, 1, MPI_COMM_WORLD, &req1);
646
647                 /*
648                  * Make sure the PR task is successful and doesn't hang.
649                  *
650                  * XXX - To test properly we need to make sure the read
651                  *       gets queued before task2's group lock request.
652                  *       You may need to increase lgbuf_size.
653                  */
654                 iter = MAX_WAIT_TRIES;
655                 do {
656                         iter--;
657                         if (!iter) {
658                                 FAIL("PR task is hung !\n");
659                                 break;
660                         }
661                         sleep(WAIT_TIME);
662                         MPI_Test(&req1, &flag1, MPI_STATUS_IGNORE);
663                 } while (!flag1);
664
665                 break;
666         }
667 }
668
669 /*
670  * task0 attempts GR(gid=1) -- granted
671  * task1 attempts PR on non-blocking fd -> should return -EWOULDBLOCK
672  * task2 attempts PW on non-blocking fd -> should return -EWOULDBLOCK
673  * task3 attempts GR(gid=2) on non-blocking fd -> should return -EWOULDBLOCK
674  */
675 void grouplock_nonblock_test(char *filename, int fd)
676 {
677         MPI_Request req1, req2, req3;
678         int iter, flag1, flag2, flag3, temp1, temp2, temp3;
679         int rc, gid = 1;
680
681         if (rank == 0) {
682                 if ((rc = ioctl(fd, LL_IOC_GROUP_LOCK, gid)) == -1) {
683                         sprintf(errmsg,
684                                 "ioctl GROUP_LOCK of file %s: (%d) %s.\n",
685                                 filename, errno, strerror(errno));
686                         FAIL(errmsg);
687                 }
688         }
689
690         rc = fcntl(fd, F_SETFL, O_NONBLOCK);
691         if (rc == -1) {
692                 sprintf(errmsg, "fcntl(O_NONBLOCK) failed: (%d) %s.\n",
693                         errno, strerror(errno));
694                 FAIL(errmsg);
695         }
696
697         MPI_Barrier(MPI_COMM_WORLD);
698
699         switch (rank) {
700         case 1:
701                 rc = read(fd, buf, sizeof(buf));
702                 if ((rc != -1) || (errno != EWOULDBLOCK))
703                         FAIL("PR lock succeeded while incompatible GROUP LOCK (gid=1) is still held\n");
704
705                 MPI_Send(&gid, 1, MPI_INT, 0, 1, MPI_COMM_WORLD);
706                 break;
707         case 2:
708                 rc = write(fd, buf, sizeof(buf));
709                 if ((rc != -1) || (errno != EWOULDBLOCK))
710                         FAIL("PW lock succeeded while incompatible GROUP LOCK (gid=1) is still held\n");
711
712                 MPI_Send(&gid, 1, MPI_INT, 0, 1, MPI_COMM_WORLD);
713                 break;
714         case 3:
715                 gid = 2;
716                 rc = ioctl(fd, LL_IOC_GROUP_LOCK, gid);
717                 if ((rc != -1) || (errno != EWOULDBLOCK))
718                         FAIL("GROUP_LOCK (gid=2) succeeded while incompatible GROUP LOCK (gid=1) is still held.\n");
719
720                 MPI_Send(&gid, 1, MPI_INT, 0, 1, MPI_COMM_WORLD);
721                 break;
722         case 0:
723                 /* reading task will tell us when it completes */
724                 MPI_Irecv(&temp1, 1, MPI_INT, 1, 1, MPI_COMM_WORLD, &req1);
725                 /* writing task will tell us when it completes */
726                 MPI_Irecv(&temp2, 1, MPI_INT, 2, 1, MPI_COMM_WORLD, &req2);
727                 /* 2nd locking task will tell us when it completes */
728                 MPI_Irecv(&temp3, 1, MPI_INT, 3, 1, MPI_COMM_WORLD, &req3);
729
730                 iter = MAX_WAIT_TRIES;
731                 do {
732                         iter--;
733                         if (!iter)
734                                 FAIL("non-blocking tasks are not progressing\n");
735
736                         sleep(WAIT_TIME);
737                         MPI_Test(&req1, &flag1, MPI_STATUS_IGNORE);
738                         MPI_Test(&req2, &flag2, MPI_STATUS_IGNORE);
739                         MPI_Test(&req3, &flag3, MPI_STATUS_IGNORE);
740                 } while (!(flag1 && flag2 && flag3));
741
742                 if ((rc = ioctl(fd, LL_IOC_GROUP_UNLOCK, gid)) == -1) {
743                         sprintf(errmsg, "ioctl GROUP_UNLOCK of file %s",
744                                 filename);
745                         FAIL(errmsg);
746                 }
747                 break;
748         }
749 }
750
751 /* Just test some error paths with invalid requests */
752 void grouplock_errorstest(char *filename, int fd)
753 {
754         int rc, gid = 1;
755
756         MPI_Barrier(MPI_COMM_WORLD);
757
758         switch (rank) {
759         case 0:
760                 if ((rc = ioctl(fd, LL_IOC_GROUP_LOCK, gid)) == -1) {
761                         sprintf(errmsg,
762                                 "ioctl GROUP_LOCK of file %s: (%d) %s.\n",
763                                 filename, errno, strerror(errno));
764                         FAIL(errmsg);
765                 }
766
767                 /* second group lock on same fd, same gid */
768                 if ((rc = ioctl(fd, LL_IOC_GROUP_LOCK, gid)) == -1) {
769                         if (errno != EINVAL) {
770                                 sprintf(errmsg,
771                                         "Double GROUP lock failed with errno %d instead of EINVAL\n",
772                                         errno);
773                                 FAIL(errmsg);
774                         }
775                 } else {
776                         FAIL("Taking second GROUP lock on same fd succeed\n");
777                 }
778
779                 /* second group lock on same fd, different gid */
780                 if ((rc = ioctl(fd, LL_IOC_GROUP_LOCK, gid + 1)) == -1) {
781                         if (errno != EINVAL) {
782                                 sprintf(errmsg,
783                                         "Double GROUP lock with different gid failed with errno %d instead of EINVAL\n",
784                                         errno);
785                                 FAIL(errmsg);
786                         }
787                 } else {
788                         FAIL("Taking second GROUP lock on same fd, with different gid, succeeded.\n");
789                 }
790
791                 /* GROUP unlock with wrong gid */
792                 if ((rc = ioctl(fd, LL_IOC_GROUP_UNLOCK, gid + 1)) == -1) {
793                         if (errno != EINVAL) {
794                                 sprintf(errmsg,
795                                         "GROUP_UNLOCK with wrong gid failed with errno %d instead of EINVAL\n",
796                                         errno);
797                                 FAIL(errmsg);
798                         }
799                 } else {
800                         FAIL("GROUP unlock with wrong gid succeed\n");
801                 }
802
803                 if ((rc = ioctl(fd, LL_IOC_GROUP_UNLOCK, gid)) == -1) {
804                         sprintf(errmsg,
805                                 "ioctl GROUP_UNLOCK of file %s returned %d.",
806                                 filename, rc);
807                         FAIL(errmsg);
808                 }
809                 break;
810
811         case 1:
812                 /* unlock of never locked fd */
813                 if ((rc = ioctl(fd, LL_IOC_GROUP_UNLOCK, gid)) == -1) {
814                         if (errno != EINVAL) {
815                                 sprintf(errmsg,
816                                         "GROUP_UNLOCK on never locked fd failed with errno %d instead of EINVAL.\n",
817                                         errno);
818                                 FAIL(errmsg);
819                         }
820                 } else {
821                         FAIL("GROUP unlock on never locked fd succeed\n");
822                 }
823                 break;
824         }
825 }
826
827 void grouplock_file(char *name, int subtest)
828 {
829         int fd;
830         int flags = O_CREAT | O_RDWR | O_SYNC | O_TRUNC;
831         int mode = 0666;
832
833         sprintf(filename, "%s/%s", testdir, name);
834
835         if ((fd = open(filename, flags, mode)) == -1) {
836                 sprintf(errmsg, "open of file %s: (%d) %s.\n",
837                         filename, errno, strerror(errno));
838                 FAIL(errmsg);
839         }
840
841         MPI_Barrier(MPI_COMM_WORLD);
842
843         switch (subtest) {
844         case 1:
845                 grouplock_test1(filename, fd, READ, IOCTL);
846                 break;
847         case 2:
848                 grouplock_test1(filename, fd, READ, CLOSE);
849                 break;
850         case 3:
851                 grouplock_test1(filename, fd, WRITE, IOCTL);
852                 break;
853         case 4:
854                 grouplock_test1(filename, fd, WRITE, CLOSE);
855                 break;
856         case 5:
857                 grouplock_test2(filename, fd, READ, IOCTL);
858                 break;
859         case 6:
860                 grouplock_test2(filename, fd, READ, CLOSE);
861                 break;
862         case 7:
863                 grouplock_test2(filename, fd, WRITE, IOCTL);
864                 break;
865         case 8:
866                 grouplock_test2(filename, fd, WRITE, CLOSE);
867                 break;
868         case 9:
869                 grouplock_nonblock_test(filename, fd);
870                 break;
871         case 10:
872                 grouplock_errorstest(filename, fd);
873                 break;
874         case 11:
875                 grouplock_test3(filename, fd);
876                 break;
877         case 12:
878                 grouplock_test4(filename, fd);
879                 break;
880         default:
881                 sprintf(errmsg, "wrong subtest number %d (should be <= %d)",
882                         subtest, LPGL_TEST_ITEMS);
883                 FAIL(errmsg);
884         }
885
886         close(fd);
887
888         if (rank == 0)
889                 unlink(filename);
890
891         MPI_Barrier(MPI_COMM_WORLD);
892 }
893
894 void parallel_grouplock(void)
895 {
896         char teststr[16];
897         int i;
898
899         if (only_test) {
900                 sprintf(teststr, "subtest %d", only_test);
901                 begin(teststr);
902                 grouplock_file("parallel_grouplock", only_test);
903                 end(teststr);
904         } else {
905                 for (i = 1; i <= LPGL_TEST_ITEMS; i++) {
906                         sprintf(teststr, "subtest %d", i);
907                         begin(teststr);
908                         grouplock_file("parallel_grouplock", i);
909                         end(teststr);
910                 }
911         }
912 }
913
914 void usage(char *proc)
915 {
916         int i;
917
918         if (rank == 0) {
919                 printf("Usage: %s [-h] -d <testdir> [-n <num>]\n", proc);
920                 printf("           [-t <num>] [-v] [-V #] [-g]\n");
921                 printf("\t-h: prints this help message\n");
922                 printf("\t-d: the directory in which the tests will run\n");
923                 printf("\t-n: repeat test # times\n");
924                 printf("\t-t: run a particular test #\n");
925                 printf("\t-v: increase the verbositly level by 1\n");
926                 printf("\t-V: select a specific verbosity level\n");
927                 printf("\t-g: debug mode\n");
928         }
929
930         MPI_Initialized(&i);
931         if (i)
932                 MPI_Finalize();
933         exit(0);
934 }
935
936 int main(int argc, char *argv[])
937 {
938         int i, iterations = 1, c;
939
940         setbuf(stdout, 0);
941         setbuf(stderr, 0);
942
943         /*
944          * Check for -h parameter before MPI_Init so the binary can be
945          * called directly, without, for instance, mpirun
946          */
947         for (i = 1; i < argc; ++i) {
948                 if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help"))
949                         usage(argv[0]);
950         }
951
952         MPI_Init(&argc, &argv);
953         MPI_Comm_rank(MPI_COMM_WORLD, &rank);
954         MPI_Comm_size(MPI_COMM_WORLD, &size);
955
956         /* Parse command line options */
957         while (1) {
958                 c = getopt(argc, argv, "d:ghn:t:vV:");
959                 if (c == -1)
960                         break;
961
962                 switch (c) {
963                 case 'd':
964                         testdir = optarg;
965                         break;
966                 case 'g':
967                         debug = 1;
968                         break;
969                 case 'h':
970                         usage(argv[0]);
971                         break;
972                 case 'n':
973                         iterations = atoi(optarg);
974                         break;
975                 case 't':
976                         only_test = atoi(optarg);
977                         break;
978                 case 'v':
979                         verbose += 1;
980                         break;
981                 case 'V':
982                         verbose = atoi(optarg);
983                         break;
984                 }
985         }
986
987         if (rank == 0)
988                 printf("%s is running with %d task(es) %s\n",
989                        argv[0], size, debug ? "in DEBUG mode" : "\b\b");
990
991         if (size < MIN_GLHOST) {
992                 fprintf(stderr,
993                         "Error: %d tasks run, but should be at least %d tasks to run the test!\n",
994                         size, MIN_GLHOST);
995                 MPI_Abort(MPI_COMM_WORLD, 2);
996         }
997
998         if (!testdir && rank == 0) {
999                 fprintf(stderr,
1000                         "Please specify a test directory! (\"%s -h\" for help)\n",
1001                         argv[0]);
1002                 MPI_Abort(MPI_COMM_WORLD, 2);
1003         }
1004
1005         lp_gethostname();
1006
1007         for (i = 0; i < iterations; ++i) {
1008                 if (rank == 0)
1009                         printf("%s: Running test #%s(iter %d)\n",
1010                                timestamp(), argv[0], i);
1011
1012                 parallel_grouplock();
1013                 MPI_Barrier(MPI_COMM_WORLD);
1014         }
1015
1016         if (rank == 0)
1017                 printf("%s: All tests passed!\n", timestamp());
1018
1019         MPI_Finalize();
1020         return 0;
1021 }