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