1 /*
2  *
3  *   Copyright (c) International Business Machines  Corp., 2001
4  *
5  *   This program is free software;  you can redistribute it and/or modify
6  *   it under the terms of the GNU General Public License as published by
7  *   the Free Software Foundation; either version 2 of the License, or
8  *   (at your option) any later version.
9  *
10  *   This program is distributed in the hope that it will be useful,
11  *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
13  *   the GNU General Public License for more details.
14  *
15  *   You should have received a copy of the GNU General Public License
16  *   along with this program;  if not, write to the Free Software
17  *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18  */
19 
20 /*
21  * NAME
22  *	fcntl16.c
23  *
24  * DESCRIPTION
25  *	Additional file locking test cases for checking proper notifictaion
26  *	of processes on lock change
27  *
28  * ALGORITHM
29  *	Various test cases are used to lock a file opened without mandatory
30  *	locking, with madatory locking and mandatory locking with NOBLOCK.
31  *	Checking that processes waiting on lock boundaries are notified
32  *	properly when boundaries change
33  *
34  * USAGE
35  *	fcntl16
36  *
37  * HISTORY
38  *	07/2001 Ported by Wayne Boyer
39  *	04/2002 wjhuie sigset cleanups
40  *
41  * RESTRICTIONS
42  *	None
43  */
44 
45 #include <fcntl.h>
46 #include <signal.h>
47 #include <errno.h>
48 #include "test.h"
49 #include "safe_macros.h"
50 #include <sys/stat.h>
51 #include <sys/types.h>
52 #include <sys/wait.h>
53 
54 
55 #define SKIPVAL 0x0f00
56 //#define       SKIP    SKIPVAL, 0, 0L, 0L, IGNORED
57 #define SKIP 0,0,0L,0L,0
58 #if (SKIPVAL == F_RDLCK) || (SKIPVAL == F_WRLCK)
59 #error invalid SKIP, must not be F_RDLCK or F_WRLCK
60 #endif
61 
62 #define	IGNORED		0
63 #define	NOBLOCK		2	/* immediate success */
64 #define	WILLBLOCK	3	/* blocks, succeeds, parent unlocks records */
65 #define	TIME_OUT	10
66 int NO_NFS = 1;			/* Test on NFS or not */
67 
68 typedef struct {
69 	struct flock parent_a;
70 	struct flock parent_b;
71 	struct flock child_a;
72 	struct flock child_b;
73 	struct flock parent_c;
74 	struct flock parent_d;
75 } testcase;
76 
77 static testcase testcases[] = {
78 	/* #1 Parent_a making a write lock on entire file */
79 	{{F_WRLCK, 0, 0L, 0L, IGNORED},
80 	 /* Parent_b skipped */
81 	 {SKIP},
82 	 /* Child_a read lock on byte 1 to byte 5 */
83 	 {F_RDLCK, 0, 0L, 5L, NOBLOCK},
84 	 /* Child_b read lock on byte 6 to byte 10 */
85 	 {F_RDLCK, 0, 6L, 5L, NOBLOCK},
86 	 /*
87 	  * Parent_c read lock on entire file
88 	  */
89 	 {F_RDLCK, 0, 0L, 0L, IGNORED},
90 	 /* Parent_d skipped */
91 	 {SKIP},},
92 
93 	/* #2 Parent_a making a write lock on entire file */
94 	{{F_WRLCK, 0, 0L, 0L, IGNORED},
95 	 /* Parent_b skipped */
96 	 {SKIP},
97 	 /* Child_a read lock on byte 1 to byte 5 */
98 	 {F_RDLCK, 0, 0L, 5L, WILLBLOCK},
99 	 /* Child_b read lock on byte 6 to byte 10 */
100 	 {F_RDLCK, 0, 6L, 5L, WILLBLOCK},
101 	 /*
102 	  * Parent_c write lock on entire
103 	  * file
104 	  */
105 	 {F_WRLCK, 0, 0L, 0L, IGNORED},
106 	 /* Parent_d skipped */
107 	 {SKIP},},
108 
109 	/* #3 Parent_a making a write lock on entire file */
110 	{{F_WRLCK, 0, 0L, 0L, IGNORED},
111 	 /* Parent_b skipped */
112 	 {SKIP},
113 	 /* Child_a read lock on byte 2 to byte 4 */
114 	 {F_RDLCK, 0, 2L, 3L, WILLBLOCK},
115 	 /* Child_b read lock on byte 6 to byte 8 */
116 	 {F_RDLCK, 0, 6L, 3L, WILLBLOCK},
117 	 /*
118 	  * Parent_c read lock on byte 3 to
119 	  * byte 7
120 	  */
121 	 {F_RDLCK, 0, 3L, 5L, IGNORED},
122 	 /* Parent_d skipped */
123 	 {SKIP},},
124 
125 	/* #4 Parent_a making a write lock on entire file */
126 	{{F_WRLCK, 0, 0L, 0L, IGNORED},
127 	 /* Parent_b skipped */
128 	 {SKIP},
129 	 /* Child_a read lock on byte 2 to byte 4 */
130 	 {F_RDLCK, 0, 2L, 3L, WILLBLOCK},
131 	 /* Child_b read lock on byte 6 to byte 8 */
132 	 {F_RDLCK, 0, 6L, 3L, NOBLOCK},
133 	 /*
134 	  * Parent_c read lock on byte 5 to
135 	  * byte 9
136 	  */
137 	 {F_RDLCK, 0, 5L, 5L, IGNORED},
138 	 /* Parent_d skipped */
139 	 {SKIP},},
140 
141 	/* #5 Parent_a making a write lock on entire file */
142 	{{F_WRLCK, 0, 0L, 0L, IGNORED},
143 	 /* Parent_b skipped */
144 	 {SKIP},
145 	 /* Child_a read lock on byte 3 to byte 7 */
146 	 {F_RDLCK, 0, 3L, 5L, NOBLOCK},
147 	 /* Child_b read lock on byte 5 to byte 10 */
148 	 {F_RDLCK, 0, 5L, 6L, WILLBLOCK},
149 	 /*
150 	  * Parent_c read lock on byte 2 to
151 	  * byte 8
152 	  */
153 	 {F_RDLCK, 0, 2L, 7L, IGNORED},
154 	 /* Parent_d skipped */
155 	 {SKIP},},
156 
157 	/* #6 Parent_a making a write lock on entire file */
158 	{{F_WRLCK, 0, 0L, 0L, IGNORED},
159 	 /* Parent_b skipped */
160 	 {SKIP},
161 	 /* Child_a read lock on byte 2 to byte 4 */
162 	 {F_RDLCK, 0, 2L, 3L, WILLBLOCK},
163 	 /* Child_b write lock on byte 6 to byte 8 */
164 	 {F_RDLCK, 0, 6L, 3L, NOBLOCK},
165 	 /* Parent_c no lock on byte 3 to 9 */
166 	 {F_UNLCK, 0, 3L, 7L, IGNORED},
167 	 /* Parent_d skipped */
168 	 {SKIP},},
169 
170 	/* #7 Parent_a making a write lock on entire file */
171 	{{F_WRLCK, 0, 0L, 0L, IGNORED},
172 	 /* Parent_b read lock on byte 3 to byte 7 */
173 	 {F_RDLCK, 0, 3L, 5L, IGNORED},
174 	 /* Child_a read lock on byte 2 to byte 4 */
175 	 {F_RDLCK, 0, 2L, 3L, NOBLOCK},
176 	 /* Child_b read lock on byte 6 to byte 8 */
177 	 {F_RDLCK, 0, 6L, 3L, NOBLOCK},
178 	 /*
179 	  * Parent_c read lock on byte 1 to
180 	  * byte 9
181 	  */
182 	 {F_RDLCK, 0, 1L, 9L, IGNORED},
183 	 /* Parent_d skipped */
184 	 {SKIP},},
185 
186 	/* #8 Parent_a making a write lock on byte 2 to byte 4 */
187 	{{F_WRLCK, 0, 2L, 3L, IGNORED},
188 	 /* Parent_b write lock on byte 6 to byte 8 */
189 	 {F_WRLCK, 0, 6L, 3L, IGNORED},
190 	 /* Child_a read lock on byte 3 to byte 7 */
191 	 {F_RDLCK, 0, 3L, 5L, NOBLOCK},
192 	 /* Child_b skipped */
193 	 {SKIP},
194 	 /*
195 	  * Parent_c read lock on byte 1 to
196 	  * byte 5
197 	  */
198 	 {F_RDLCK, 0, 1L, 5L, IGNORED},
199 	 /*
200 	  * Parent_d read lock on
201 	  * byte 5 to byte 9
202 	  */
203 	 {F_RDLCK, 0, 5L, 5L,
204 	  IGNORED},},
205 
206 	/* #9 Parent_a making a write lock on entire file */
207 	{{F_WRLCK, 0, 0L, 0L, IGNORED},
208 	 /* Parent_b read lock on byte 3 to byte 7 */
209 	 {F_RDLCK, 0, 3L, 5L, IGNORED},
210 	 /* Child_a read lock on byte 2 to byte 4 */
211 	 {F_RDLCK, 0, 2L, 3L, NOBLOCK},
212 	 /* Child_b read lock on byte 6 to byte 8 */
213 	 {F_RDLCK, 0, 6L, 3L, NOBLOCK},
214 	 /*
215 	  * Parent_c read lock on byte 1 to
216 	  * byte 3
217 	  */
218 	 {F_RDLCK, 0, 1L, 3L, IGNORED},
219 	 /*
220 	  * Parent_d read lock on
221 	  * byte 7 to byte 9
222 	  */
223 	 {F_RDLCK, 0, 7L, 3L,
224 	  IGNORED},},
225 
226 	/* #10 Parent_a making a write lock on entire file */
227 	{{F_WRLCK, 0, 0L, 0L, IGNORED},
228 	 /* Parent_b skipped */
229 	 {SKIP},
230 	 /* Child_a read lock on byte 2 to byte 4 */
231 	 {F_RDLCK, 0, 2L, 3L, NOBLOCK},
232 	 /* Child_b read lock on byte 6 to byte 8 */
233 	 {F_RDLCK, 0, 6L, 3L, NOBLOCK},
234 	 /*
235 	  * Parent_c read lock on byte 1 to
236 	  * byte 7
237 	  */
238 	 {F_RDLCK, 0, 1L, 7L, IGNORED},
239 	 /*
240 	  * Parent_d read lock on
241 	  * byte 3 to byte 9
242 	  */
243 	 {F_RDLCK, 0, 3L, 7L,
244 	  IGNORED},},
245 
246 	/* #11 Parent_a making a write lock on entire file */
247 	{{F_WRLCK, 0, 0L, 0L, IGNORED},
248 	 /* Parent_b skipped */
249 	 {SKIP},
250 	 /* Child_a read lock on byte 3 to byte 7 */
251 	 {F_RDLCK, 0, 3L, 5L, NOBLOCK},
252 	 /* Child_b read lock on byte 3 to byte 7 */
253 	 {F_RDLCK, 0, 3L, 5L, NOBLOCK},
254 	 /*
255 	  * Parent_c read lock on byte 3 to
256 	  * byte 7
257 	  */
258 	 {F_RDLCK, 0, 3L, 5L, IGNORED},
259 	 /* Parent_d skipped */
260 	 {SKIP},},
261 };
262 
263 static testcase *thiscase;
264 static struct flock *thislock;
265 static int parent;
266 static int child_flag1 = 0;
267 static int child_flag2 = 0;
268 static int parent_flag = 0;
269 static int alarm_flag = 0;
270 static int child_pid[2], flag[2];
271 static int fd;
272 static int test;
273 static char tmpname[40];
274 
275 #define	FILEDATA	"tenbytes!"
276 
277 extern void catch_int(int sig);	/* signal catching subroutine */
278 
279 char *TCID = "fcntl16";
280 int TST_TOTAL = 1;
281 
282 #ifdef UCLINUX
283 static char *argv0;
284 #endif
285 
286 /*
287  * cleanup - performs all the ONE TIME cleanup for this test at completion or
288  *	premature exit
289  */
cleanup(void)290 void cleanup(void)
291 {
292 	tst_rmdir();
293 
294 }
295 
dochild(int kid)296 void dochild(int kid)
297 {
298 	/* child process */
299 	struct sigaction sact;
300 	sact.sa_flags = 0;
301 	sact.sa_handler = catch_int;
302 	sigemptyset(&sact.sa_mask);
303 	(void)sigaction(SIGUSR1, &sact, NULL);
304 
305 	/* Lock should succeed after blocking and parent releases lock */
306 	if (kid) {
307 		if ((kill(parent, SIGUSR2)) < 0) {
308 			tst_resm(TFAIL, "Attempt to send signal to parent "
309 				 "failed");
310 			tst_resm(TFAIL, "Test case %d, child %d, errno = %d",
311 				 test + 1, kid, errno);
312 			exit(1);
313 		}
314 	} else {
315 		if ((kill(parent, SIGUSR1)) < 0) {
316 			tst_resm(TFAIL, "Attempt to send signal to parent "
317 				 "failed");
318 			tst_resm(TFAIL, "Test case %d, child %d, errno = %d",
319 				 test + 1, kid, errno);
320 			exit(1);
321 		}
322 	}
323 
324 	if ((fcntl(fd, F_SETLKW, thislock)) < 0) {
325 		if (errno == EINTR && parent_flag) {
326 			/*
327 			 * signal received is waiting for lock to clear,
328 			 * this is expected if flag = WILLBLOCK
329 			 */
330 			exit(1);
331 		} else {
332 			tst_resm(TFAIL, "Attempt to set child BLOCKING lock "
333 				 "failed");
334 			tst_resm(TFAIL, "Test case %d, errno = %d", test + 1,
335 				 errno);
336 			exit(2);
337 		}
338 	}
339 	exit(0);
340 }				/* end of child process */
341 
342 #ifdef UCLINUX
343 static int kid_uc;
344 
dochild_uc(void)345 void dochild_uc(void)
346 {
347 	dochild(kid_uc);
348 }
349 #endif
350 
catch_alarm(int sig)351 void catch_alarm(int sig)
352 {
353 	alarm_flag = 1;
354 }
355 
catch_usr1(int sig)356 void catch_usr1(int sig)
357 {				/* invoked on catching SIGUSR1 */
358 	/*
359 	 * Set flag to let parent know that child #1 is ready to have the
360 	 * lock removed
361 	 */
362 	child_flag1 = 1;
363 }
364 
catch_usr2(int sig)365 void catch_usr2(int sig)
366 {				/* invoked on catching SIGUSR2 */
367 	/*
368 	 * Set flag to let parent know that child #2 is ready to have the
369 	 * lock removed
370 	 */
371 	child_flag2 = 1;
372 }
373 
catch_int(int sig)374 void catch_int(int sig)
375 {				/* invoked on child catching SIGUSR1 */
376 	/*
377 	 * Set flag to interrupt fcntl call in child and force a controlled
378 	 * exit
379 	 */
380 	parent_flag = 1;
381 }
382 
child_sig(int sig,int nkids)383 void child_sig(int sig, int nkids)
384 {
385 	int i;
386 
387 	for (i = 0; i < nkids; i++) {
388 		if (kill(child_pid[i], 0) == 0) {
389 			if ((kill(child_pid[i], sig)) < 0) {
390 				tst_resm(TFAIL, "Attempt to signal child %d, "
391 					 "failed", i + 1);
392 			}
393 		}
394 	}
395 }
396 
397 /*
398  * setup - performs all ONE TIME steup for this test
399  */
setup(void)400 void setup(void)
401 {
402 	struct sigaction sact;
403 
404 	tst_sig(FORK, DEF_HANDLER, cleanup);
405 
406 	umask(0);
407 
408 	/* Pause if option was specified */
409 	TEST_PAUSE;
410 
411 	parent = getpid();
412 
413 	tst_tmpdir();
414 
415 	/* On NFS or not */
416 	if (tst_fs_type(cleanup, ".") == TST_NFS_MAGIC)
417 		NO_NFS = 0;
418 
419 	/* set up temp filename */
420 	sprintf(tmpname, "fcntl4.%d", parent);
421 
422 	/*
423 	 * Set up signal handling functions
424 	 */
425 	memset(&sact, 0, sizeof(sact));
426 	sact.sa_handler = catch_usr1;
427 	sigemptyset(&sact.sa_mask);
428 	sigaddset(&sact.sa_mask, SIGUSR1);
429 	sigaction(SIGUSR1, &sact, NULL);
430 
431 	memset(&sact, 0, sizeof(sact));
432 	sact.sa_handler = catch_usr2;
433 	sigemptyset(&sact.sa_mask);
434 	sigaddset(&sact.sa_mask, SIGUSR2);
435 	sigaction(SIGUSR2, &sact, NULL);
436 
437 	memset(&sact, 0, sizeof(sact));
438 	sact.sa_handler = catch_alarm;
439 	sigemptyset(&sact.sa_mask);
440 	sigaddset(&sact.sa_mask, SIGALRM);
441 	sigaction(SIGALRM, &sact, NULL);
442 }
443 
run_test(int file_flag,int file_mode,int start,int end)444 int run_test(int file_flag, int file_mode, int start, int end)
445 {
446 	int child_count;
447 	int child;
448 	int nexited;
449 	int status, expect_stat;
450 	int i, fail = 0;
451 
452 	/* loop through all test cases */
453 	for (test = start; test < end; test++) {
454 		/* open a temp file to lock */
455 		fd = SAFE_OPEN(cleanup, tmpname, file_flag, file_mode);
456 
457 		/* write some dummy data to the file */
458 		(void)write(fd, FILEDATA, 10);
459 
460 		/* Initialize first parent lock structure */
461 		thiscase = &testcases[test];
462 		thislock = &thiscase->parent_a;
463 
464 		/* set the initial parent lock on the file */
465 		if ((fcntl(fd, F_SETLK, thislock)) < 0) {
466 			tst_resm(TFAIL, "First parent lock failed");
467 			tst_resm(TFAIL, "Test case %d, errno = %d", test + 1,
468 				 errno);
469 			close(fd);
470 			unlink(tmpname);
471 			return 1;
472 		}
473 
474 		/* Initialize second parent lock structure */
475 		thislock = &thiscase->parent_b;
476 
477 		if ((thislock->l_type) != IGNORED) {	/*SKIPVAL */
478 			/* set the second parent lock */
479 			if ((fcntl(fd, F_SETLK, thislock)) < 0) {
480 				tst_resm(TFAIL, "Second parent lock failed");
481 				tst_resm(TFAIL, "Test case %d, errno = %d",
482 					 test + 1, errno);
483 				close(fd);
484 				unlink(tmpname);
485 				return 1;
486 			}
487 		}
488 
489 		/* Initialize first child lock structure */
490 		thislock = &thiscase->child_a;
491 
492 		/* Initialize child counter and flags */
493 		alarm_flag = parent_flag = 0;
494 		child_flag1 = child_flag2 = 0;
495 		child_count = 0;
496 
497 		/* spawn child processes */
498 		for (i = 0; i < 2; i++) {
499 			if (thislock->l_type != IGNORED) {
500 				if ((child = FORK_OR_VFORK()) == 0) {
501 #ifdef UCLINUX
502 					if (self_exec(argv0, "ddddd", i, parent,
503 						      test, thislock, fd) < 0) {
504 						perror("self_exec failed");
505 						return 1;
506 					}
507 #else
508 					dochild(i);
509 #endif
510 				}
511 				if (child < 0) {
512 					perror("Fork failed");
513 					return 1;
514 				}
515 				child_count++;
516 				child_pid[i] = child;
517 				flag[i] = thislock->l_pid;
518 			}
519 			/* Initialize second child lock structure */
520 			thislock = &thiscase->child_b;
521 		}
522 		/* parent process */
523 
524 		/*
525 		 * Wait for children to signal they are ready. Set a timeout
526 		 * just in case they don't signal at all.
527 		 */
528 		alarm(TIME_OUT);
529 
530 		while (!alarm_flag
531 		       && (child_flag1 + child_flag2 != child_count)) {
532 			pause();
533 		}
534 
535 		/*
536 		 * Turn off alarm and unmask signals
537 		 */
538 		alarm((unsigned)0);
539 
540 		if (child_flag1 + child_flag2 != child_count) {
541 			tst_resm(TFAIL, "Test case %d: kids didn't signal",
542 				 test + 1);
543 			fail = 1;
544 		}
545 		child_flag1 = child_flag2 = alarm_flag = 0;
546 
547 		thislock = &thiscase->parent_c;
548 
549 		/* set the third parent lock on the file */
550 		if ((fcntl(fd, F_SETLK, thislock)) < 0) {
551 			tst_resm(TFAIL, "Third parent lock failed");
552 			tst_resm(TFAIL, "Test case %d, errno = %d",
553 				 test + 1, errno);
554 			close(fd);
555 			unlink(tmpname);
556 			return 1;
557 		}
558 
559 		/* Initialize fourth parent lock structure */
560 		thislock = &thiscase->parent_d;
561 
562 		if ((thislock->l_type) != IGNORED) {	/*SKIPVAL */
563 			/* set the fourth parent lock */
564 			if ((fcntl(fd, F_SETLK, thislock)) < 0) {
565 				tst_resm(TINFO, "Fourth parent lock failed");
566 				tst_resm(TINFO, "Test case %d, errno = %d",
567 					 test + 1, errno);
568 				close(fd);
569 				unlink(tmpname);
570 				return 1;
571 			}
572 		}
573 
574 		/*
575 		 * Wait for children to exit, or for timeout to occur.
576 		 * Timeouts are expected for testcases where kids are
577 		 * 'WILLBLOCK', In that case, send kids a wakeup interrupt
578 		 * and wait again for them. If a second timeout occurs, then
579 		 * something is wrong.
580 		 */
581 		alarm_flag = nexited = 0;
582 		while (nexited < child_count) {
583 			alarm(TIME_OUT);
584 			child = wait(&status);
585 			alarm(0);
586 
587 			if (child == -1) {
588 				if (errno != EINTR || alarm_flag != 1) {
589 					/*
590 					 * Some error other than a timeout,
591 					 * or else this is the second
592 					 * timeout. Both cases are errors.
593 					 */
594 					break;
595 				}
596 
597 				/*
598 				 * Expected timeout case. Signal kids then
599 				 * go back and wait again
600 				 */
601 				child_sig(SIGUSR1, child_count);
602 				continue;
603 			}
604 
605 			for (i = 0; i < child_count; i++)
606 				if (child == child_pid[i])
607 					break;
608 			if (i == child_count) {
609 				/*
610 				 * Ignore unexpected kid, it could be a
611 				 * leftover from a previous iteration that
612 				 * timed out.
613 				 */
614 				continue;
615 			}
616 
617 			/* Found the right kid, check his status */
618 			nexited++;
619 
620 			expect_stat = (flag[i] == NOBLOCK) ? 0 : 1;
621 
622 			if (!WIFEXITED(status)
623 			    || WEXITSTATUS(status) != expect_stat) {
624 				/* got unexpected exit status from kid */
625 				tst_resm(TFAIL, "Test case %d: child %d %s "
626 					 "or got bad status (x%x)", test + 1,
627 					 i, (flag[i] == NOBLOCK) ?
628 					 "BLOCKED unexpectedly" :
629 					 "failed to BLOCK", status);
630 				fail = 1;
631 			}
632 		}
633 
634 		if (nexited != child_count) {
635 			tst_resm(TFAIL, "Test case %d, caught %d expected %d "
636 				 "children", test + 1, nexited, child_count);
637 			child_sig(SIGKILL, nexited);
638 			fail = 1;
639 		}
640 		close(fd);
641 	}
642 	unlink(tmpname);
643 	if (fail) {
644 		return 1;
645 	} else {
646 		return 0;
647 	}
648 	return 0;
649 }
650 
main(int ac,char ** av)651 int main(int ac, char **av)
652 {
653 
654 	int lc;
655 
656 	tst_parse_opts(ac, av, NULL, NULL);
657 #ifdef UCLINUX
658 	maybe_run_child(dochild_uc, "ddddd", &kid_uc, &parent, &test,
659 			&thislock, &fd);
660 	argv0 = av[0];
661 #endif
662 
663 	setup();		/* global setup */
664 
665 	for (lc = 0; TEST_LOOPING(lc); lc++) {
666 		/* reset tst_count in case we are looping */
667 		tst_count = 0;
668 
669 /* //block1: */
670 		/*
671 		 * Check file locks on an ordinary file without
672 		 * mandatory locking
673 		 */
674 		tst_resm(TINFO, "Entering block 1");
675 		if (run_test(O_CREAT | O_RDWR | O_TRUNC, 0777, 0, 11)) {
676 			tst_resm(TINFO, "Test case 1: without mandatory "
677 				 "locking FAILED");
678 		} else {
679 			tst_resm(TINFO, "Test case 1: without manadatory "
680 				 "locking PASSED");
681 		}
682 		tst_resm(TINFO, "Exiting block 1");
683 
684 /* //block2: */
685 		/*
686 		 * Check the file locks on a file with mandatory record
687 		 * locking
688 		 */
689 		tst_resm(TINFO, "Entering block 2");
690 		if (NO_NFS && run_test(O_CREAT | O_RDWR | O_TRUNC, S_ISGID |
691 			     S_IRUSR | S_IWUSR, 0, 11)) {
692 			tst_resm(TINFO, "Test case 2: with mandatory record "
693 				 "locking FAILED");
694 		} else {
695 			if (NO_NFS)
696 				tst_resm(TINFO, "Test case 2: with mandatory"
697 					 " record locking PASSED");
698 			else
699 				tst_resm(TCONF, "Test case 2: NFS does not"
700 					 " support mandatory locking");
701 		}
702 		tst_resm(TINFO, "Exiting block 2");
703 
704 /* //block3: */
705 		/*
706 		 * Check file locks on a file with mandatory record locking
707 		 * and no delay
708 		 */
709 		tst_resm(TINFO, "Entering block 3");
710 		if (NO_NFS && run_test(O_CREAT | O_RDWR | O_TRUNC | O_NDELAY,
711 			     S_ISGID | S_IRUSR | S_IWUSR, 0, 11)) {
712 			tst_resm(TINFO, "Test case 3: mandatory locking with "
713 				 "NODELAY FAILED");
714 		} else {
715 			if (NO_NFS)
716 				tst_resm(TINFO, "Test case 3: mandatory"
717 					 " locking with NODELAY PASSED");
718 			else
719 				tst_resm(TCONF, "Test case 3: NFS does not"
720 					 " support mandatory locking");
721 		}
722 		tst_resm(TINFO, "Exiting block 3");
723 	}
724 	cleanup();
725 	tst_exit();
726 }
727