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