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