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