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