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