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