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