flock_helper.c revision 298490
1/*-
2 * Copyright (c) 2008 Isilon Inc http://www.isilon.com/
3 * Authors: Doug Rabson <dfr@rabson.org>
4 * Developed with Red Inc: Alfred Perlstein <alfred@freebsd.org>
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 * $FreeBSD: stable/10/tests/sys/file/flock_helper.c 298490 2016-04-22 21:30:42Z ngie $
28 */
29
30#include <sys/param.h>
31#include <sys/file.h>
32#include <sys/time.h>
33#ifdef __FreeBSD__
34#include <sys/mount.h>
35#endif
36#include <sys/stat.h>
37#include <sys/wait.h>
38
39#include <err.h>
40#include <errno.h>
41#include <fcntl.h>
42#include <pthread.h>
43#include <signal.h>
44#include <stdint.h>
45#include <stdio.h>
46#include <stdlib.h>
47#include <string.h>
48#include <unistd.h>
49
50#ifdef __FreeBSD__
51#if __FreeBSD_version >= 800028
52#define HAVE_SYSID
53#endif
54#include <sys/cdefs.h>
55#else
56#ifndef nitems
57#define	nitems(x)	(sizeof((x)) / sizeof((x)[0]))
58#endif
59
60#ifndef __unused
61#ifdef __GNUC__
62#define	__unused	__attribute__((__unused__))
63#else
64#define __unused
65#endif
66#endif
67#endif
68
69static int verbose = 0;
70
71static int
72make_file(const char *pathname, off_t sz)
73{
74	struct stat st;
75	const char *template = "/flocktempXXXXXX";
76	size_t len;
77	char *filename;
78	int fd;
79
80	if (stat(pathname, &st) == 0) {
81		if (S_ISREG(st.st_mode)) {
82			fd = open(pathname, O_RDWR);
83			if (fd < 0)
84				err(1, "open(%s)", pathname);
85			if (ftruncate(fd, sz) < 0)
86				err(1, "ftruncate");
87			return (fd);
88		}
89	}
90
91	len = strlen(pathname) + strlen(template) + 1;
92	filename = malloc(len);
93	strcpy(filename, pathname);
94	strcat(filename, template);
95	fd = mkstemp(filename);
96	if (fd < 0)
97		err(1, "mkstemp");
98	if (ftruncate(fd, sz) < 0)
99		err(1, "ftruncate");
100	if (unlink(filename) < 0)
101		err(1, "unlink");
102	free(filename);
103
104	return (fd);
105}
106
107static void
108ignore_alarm(int __unused sig)
109{
110}
111
112static int
113safe_waitpid(pid_t pid)
114{
115	int save_errno;
116	int status;
117
118	save_errno = errno;
119	errno = 0;
120	while (waitpid(pid, &status, 0) != pid) {
121		if (errno == EINTR)
122			continue;
123		err(1, "waitpid");
124	}
125	errno = save_errno;
126
127	return (status);
128}
129
130#define FAIL(test)					\
131	do {						\
132		if (test) {				\
133			printf("FAIL (%s)\n", #test);	\
134			return -1;			\
135		}					\
136	} while (0)
137
138#define SUCCEED \
139	do { printf("SUCCEED\n"); return 0; } while (0)
140
141/*
142 * Test 1 - F_GETLK on unlocked region
143 *
144 * If no lock is found that would prevent this lock from being
145 * created, the structure is left unchanged by this function call
146 * except for the lock type which is set to F_UNLCK.
147 */
148static int
149test1(int fd, __unused int argc, const __unused char **argv)
150{
151	struct flock fl1, fl2;
152
153	memset(&fl1, 1, sizeof(fl1));
154	fl1.l_type = F_WRLCK;
155	fl1.l_whence = SEEK_SET;
156	fl2 = fl1;
157
158	if (fcntl(fd, F_GETLK, &fl1) < 0)
159		err(1, "F_GETLK");
160
161	printf("1 - F_GETLK on unlocked region: ");
162	FAIL(fl1.l_start != fl2.l_start);
163	FAIL(fl1.l_len != fl2.l_len);
164	FAIL(fl1.l_pid != fl2.l_pid);
165	FAIL(fl1.l_type != F_UNLCK);
166	FAIL(fl1.l_whence != fl2.l_whence);
167#ifdef HAVE_SYSID
168	FAIL(fl1.l_sysid != fl2.l_sysid);
169#endif
170
171	SUCCEED;
172}
173
174/*
175 * Test 2 - F_SETLK on locked region
176 *
177 * If a shared or exclusive lock cannot be set, fcntl returns
178 * immediately with EACCES or EAGAIN.
179 */
180static int
181test2(int fd, __unused int argc, const __unused char **argv)
182{
183	/*
184	 * We create a child process to hold the lock which we will
185	 * test. We use a pipe to communicate with the child.
186	 */
187	int pid;
188	int pfd[2];
189	struct flock fl;
190	char ch;
191	int res;
192
193	if (pipe(pfd) < 0)
194		err(1, "pipe");
195
196	fl.l_start = 0;
197	fl.l_len = 0;
198	fl.l_type = F_WRLCK;
199	fl.l_whence = SEEK_SET;
200
201	pid = fork();
202	if (pid < 0)
203		err(1, "fork");
204
205	if (pid == 0) {
206		/*
207		 * We are the child. We set a write lock and then
208		 * write one byte back to the parent to tell it. The
209		 * parent will kill us when its done.
210		 */
211		if (fcntl(fd, F_SETLK, &fl) < 0)
212			err(1, "F_SETLK (child)");
213		if (write(pfd[1], "a", 1) < 0)
214			err(1, "writing to pipe (child)");
215		pause();
216		exit(0);
217	}
218
219	/*
220	 * Wait until the child has set its lock and then perform the
221	 * test.
222	 */
223	if (read(pfd[0], &ch, 1) != 1)
224		err(1, "reading from pipe (child)");
225
226	/*
227	 * fcntl should return -1 with errno set to either EACCES or
228	 * EAGAIN.
229	 */
230	printf("2 - F_SETLK on locked region: ");
231	res = fcntl(fd, F_SETLK, &fl);
232	kill(pid, SIGTERM);
233	safe_waitpid(pid);
234	close(pfd[0]);
235	close(pfd[1]);
236	FAIL(res == 0);
237	FAIL(errno != EACCES && errno != EAGAIN);
238
239	SUCCEED;
240}
241
242/*
243 * Test 3 - F_SETLKW on locked region
244 *
245 * If a shared or exclusive lock is blocked by other locks, the
246 * process waits until the request can be satisfied.
247 *
248 * XXX this test hangs on FreeBSD NFS filesystems due to limitations
249 * in FreeBSD's client (and server) lockd implementation.
250 */
251static int
252test3(int fd, __unused int argc, const __unused char **argv)
253{
254	/*
255	 * We create a child process to hold the lock which we will
256	 * test. We use a pipe to communicate with the child.
257	 */
258	int pid;
259	int pfd[2];
260	struct flock fl;
261	char ch;
262	int res;
263
264	if (pipe(pfd) < 0)
265		err(1, "pipe");
266
267	fl.l_start = 0;
268	fl.l_len = 0;
269	fl.l_type = F_WRLCK;
270	fl.l_whence = SEEK_SET;
271
272	pid = fork();
273	if (pid < 0)
274		err(1, "fork");
275
276	if (pid == 0) {
277		/*
278		 * We are the child. We set a write lock and then
279		 * write one byte back to the parent to tell it. The
280		 * parent will kill us when its done.
281		 */
282		if (fcntl(fd, F_SETLK, &fl) < 0)
283			err(1, "F_SETLK (child)");
284		if (write(pfd[1], "a", 1) < 0)
285			err(1, "writing to pipe (child)");
286		pause();
287		exit(0);
288	}
289
290	/*
291	 * Wait until the child has set its lock and then perform the
292	 * test.
293	 */
294	if (read(pfd[0], &ch, 1) != 1)
295		err(1, "reading from pipe (child)");
296
297	/*
298	 * fcntl should wait until the alarm and then return -1 with
299	 * errno set to EINTR.
300	 */
301	printf("3 - F_SETLKW on locked region: ");
302
303	alarm(1);
304
305	res = fcntl(fd, F_SETLKW, &fl);
306	kill(pid, SIGTERM);
307	safe_waitpid(pid);
308	close(pfd[0]);
309	close(pfd[1]);
310	FAIL(res == 0);
311	FAIL(errno != EINTR);
312
313	SUCCEED;
314}
315
316/*
317 * Test 4 - F_GETLK on locked region
318 *
319 * Get the first lock that blocks the lock.
320 */
321static int
322test4(int fd, __unused int argc, const __unused char **argv)
323{
324	/*
325	 * We create a child process to hold the lock which we will
326	 * test. We use a pipe to communicate with the child.
327	 */
328	int pid;
329	int pfd[2];
330	struct flock fl;
331	char ch;
332
333	if (pipe(pfd) < 0)
334		err(1, "pipe");
335
336	fl.l_start = 0;
337	fl.l_len = 99;
338	fl.l_type = F_WRLCK;
339	fl.l_whence = SEEK_SET;
340
341	pid = fork();
342	if (pid < 0)
343		err(1, "fork");
344
345	if (pid == 0) {
346		/*
347		 * We are the child. We set a write lock and then
348		 * write one byte back to the parent to tell it. The
349		 * parent will kill us when its done.
350		 */
351		if (fcntl(fd, F_SETLK, &fl) < 0)
352			err(1, "F_SETLK (child)");
353		if (write(pfd[1], "a", 1) < 0)
354			err(1, "writing to pipe (child)");
355		pause();
356		exit(0);
357	}
358
359	/*
360	 * Wait until the child has set its lock and then perform the
361	 * test.
362	 */
363	if (read(pfd[0], &ch, 1) != 1)
364		err(1, "reading from pipe (child)");
365
366	/*
367	 * fcntl should return a lock structure reflecting the lock we
368	 * made in the child process.
369	 */
370	if (fcntl(fd, F_GETLK, &fl) < 0)
371		err(1, "F_GETLK");
372
373	printf("4 - F_GETLK on locked region: ");
374	FAIL(fl.l_start != 0);
375	FAIL(fl.l_len != 99);
376	FAIL(fl.l_type != F_WRLCK);
377	FAIL(fl.l_pid != pid);
378#ifdef HAVE_SYSID
379	FAIL(fl.l_sysid != 0);
380#endif
381
382	kill(pid, SIGTERM);
383	safe_waitpid(pid);
384	close(pfd[0]);
385	close(pfd[1]);
386
387	SUCCEED;
388}
389
390/*
391 * Test 5 - F_SETLKW simple deadlock
392 *
393 * If a blocking shared lock request would cause a deadlock (i.e. the
394 * lock request is blocked by a process which is itself blocked on a
395 * lock currently owned by the process making the new request),
396 * EDEADLK is returned.
397 */
398static int
399test5(int fd, __unused int argc, const __unused char **argv)
400{
401	/*
402	 * We create a child process to hold the lock which we will
403	 * test. Because our test relies on the child process being
404	 * blocked on the parent's lock, we can't easily use a pipe to
405	 * synchronize so we just sleep in the parent to given the
406	 * child a chance to setup.
407	 *
408	 * To create the deadlock condition, we arrange for the parent
409	 * to lock the first byte of the file and the child to lock
410	 * the second byte.  After locking the second byte, the child
411	 * will attempt to lock the first byte of the file, and
412	 * block. The parent will then attempt to lock the second byte
413	 * (owned by the child) which should cause deadlock.
414	 */
415	int pid;
416	struct flock fl;
417	int res;
418
419	/*
420	 * Lock the first byte in the parent.
421	 */
422	fl.l_start = 0;
423	fl.l_len = 1;
424	fl.l_type = F_WRLCK;
425	fl.l_whence = SEEK_SET;
426	if (fcntl(fd, F_SETLK, &fl) < 0)
427		err(1, "F_SETLK 1 (parent)");
428
429	pid = fork();
430	if (pid < 0)
431		err(1, "fork");
432
433	if (pid == 0) {
434		/*
435		 * Lock the second byte in the child and then block on
436		 * the parent's lock.
437		 */
438		fl.l_start = 1;
439		if (fcntl(fd, F_SETLK, &fl) < 0)
440			err(1, "F_SETLK (child)");
441		fl.l_start = 0;
442		if (fcntl(fd, F_SETLKW, &fl) < 0)
443			err(1, "F_SETLKW (child)");
444		exit(0);
445	}
446
447	/*
448	 * Wait until the child has set its lock and then perform the
449	 * test.
450	 */
451	sleep(1);
452
453	/*
454	 * fcntl should immediately return -1 with errno set to
455	 * EDEADLK. If the alarm fires, we failed to detect the
456	 * deadlock.
457	 */
458	alarm(1);
459	printf("5 - F_SETLKW simple deadlock: ");
460
461	fl.l_start = 1;
462	res = fcntl(fd, F_SETLKW, &fl);
463	kill(pid, SIGTERM);
464	safe_waitpid(pid);
465
466	FAIL(res == 0);
467	FAIL(errno != EDEADLK);
468
469	fl.l_start = 0;
470	fl.l_len = 0;
471	fl.l_type = F_UNLCK;
472	if (fcntl(fd, F_SETLK, &fl) < 0)
473		err(1, "F_UNLCK");
474
475	/*
476	 * Cancel the alarm to avoid confusing later tests.
477	 */
478	alarm(0);
479
480	SUCCEED;
481}
482
483/*
484 * Test 6 - F_SETLKW complex deadlock.
485 *
486 * This test involves three process, P, C1 and C2. We set things up so
487 * that P locks byte zero, C1 locks byte 1 and C2 locks byte 2. We
488 * also block C2 by attempting to lock byte zero. Lastly, P attempts
489 * to lock a range including byte 1 and 2. This represents a deadlock
490 * (due to C2's blocking attempt to lock byte zero).
491 */
492static int
493test6(int fd, __unused int argc, const __unused char **argv)
494{
495	/*
496	 * Because our test relies on the child process being blocked
497	 * on the parent's lock, we can't easily use a pipe to
498	 * synchronize so we just sleep in the parent to given the
499	 * children a chance to setup.
500	 */
501	int pid1, pid2;
502	struct flock fl;
503	int res;
504
505	/*
506	 * Lock the first byte in the parent.
507	 */
508	fl.l_start = 0;
509	fl.l_len = 1;
510	fl.l_type = F_WRLCK;
511	fl.l_whence = SEEK_SET;
512	if (fcntl(fd, F_SETLK, &fl) < 0)
513		err(1, "F_SETLK 1 (parent)");
514
515	pid1 = fork();
516	if (pid1 < 0)
517		err(1, "fork");
518
519	if (pid1 == 0) {
520		/*
521		 * C1
522		 * Lock the second byte in the child and then sleep
523		 */
524		fl.l_start = 1;
525		if (fcntl(fd, F_SETLK, &fl) < 0)
526			err(1, "F_SETLK (child1)");
527		pause();
528		exit(0);
529	}
530
531	pid2 = fork();
532	if (pid2 < 0)
533		err(1, "fork");
534
535	if (pid2 == 0) {
536		/*
537		 * C2
538		 * Lock the third byte in the child and then block on
539		 * the parent's lock.
540		 */
541		fl.l_start = 2;
542		if (fcntl(fd, F_SETLK, &fl) < 0)
543			err(1, "F_SETLK (child2)");
544		fl.l_start = 0;
545		if (fcntl(fd, F_SETLKW, &fl) < 0)
546			err(1, "F_SETLKW (child2)");
547		exit(0);
548	}
549
550	/*
551	 * Wait until the children have set their locks and then
552	 * perform the test.
553	 */
554	sleep(1);
555
556	/*
557	 * fcntl should immediately return -1 with errno set to
558	 * EDEADLK. If the alarm fires, we failed to detect the
559	 * deadlock.
560	 */
561	alarm(1);
562	printf("6 - F_SETLKW complex deadlock: ");
563
564	fl.l_start = 1;
565	fl.l_len = 2;
566	res = fcntl(fd, F_SETLKW, &fl);
567	kill(pid1, SIGTERM);
568	safe_waitpid(pid1);
569	kill(pid2, SIGTERM);
570	safe_waitpid(pid2);
571
572	fl.l_start = 0;
573	fl.l_len = 0;
574	fl.l_type = F_UNLCK;
575	if (fcntl(fd, F_SETLK, &fl) < 0)
576		err(1, "F_UNLCK");
577
578	FAIL(res == 0);
579	FAIL(errno != EDEADLK);
580
581	/*
582	 * Cancel the alarm to avoid confusing later tests.
583	 */
584	alarm(0);
585
586	SUCCEED;
587}
588
589/*
590 * Test 7 - F_SETLK shared lock on exclusive locked region
591 *
592 * If a shared or exclusive lock cannot be set, fcntl returns
593 * immediately with EACCES or EAGAIN.
594 */
595static int
596test7(int fd, __unused int argc, const __unused char **argv)
597{
598	/*
599	 * We create a child process to hold the lock which we will
600	 * test. We use a pipe to communicate with the child.
601	 */
602	int pid;
603	int pfd[2];
604	struct flock fl;
605	char ch;
606	int res;
607
608	if (pipe(pfd) < 0)
609		err(1, "pipe");
610
611	fl.l_start = 0;
612	fl.l_len = 0;
613	fl.l_type = F_WRLCK;
614	fl.l_whence = SEEK_SET;
615
616	pid = fork();
617	if (pid < 0)
618		err(1, "fork");
619
620	if (pid == 0) {
621		/*
622		 * We are the child. We set a write lock and then
623		 * write one byte back to the parent to tell it. The
624		 * parent will kill us when its done.
625		 */
626		if (fcntl(fd, F_SETLK, &fl) < 0)
627			err(1, "F_SETLK (child)");
628		if (write(pfd[1], "a", 1) < 0)
629			err(1, "writing to pipe (child)");
630		pause();
631		exit(0);
632	}
633
634	/*
635	 * Wait until the child has set its lock and then perform the
636	 * test.
637	 */
638	if (read(pfd[0], &ch, 1) != 1)
639		err(1, "reading from pipe (child)");
640
641	/*
642	 * fcntl should wait until the alarm and then return -1 with
643	 * errno set to EINTR.
644	 */
645	printf("7 - F_SETLK shared lock on exclusive locked region: ");
646
647	fl.l_type = F_RDLCK;
648	res = fcntl(fd, F_SETLK, &fl);
649	kill(pid, SIGTERM);
650	safe_waitpid(pid);
651	close(pfd[0]);
652	close(pfd[1]);
653
654	FAIL(res == 0);
655	FAIL(errno != EACCES && errno != EAGAIN);
656
657	SUCCEED;
658}
659
660/*
661 * Test 8 - F_SETLK shared lock on share locked region
662 *
663 * When a shared lock is set on a segment of a file, other processes
664 * shall be able to set shared locks on that segment or a portion of
665 * it.
666 */
667static int
668test8(int fd, __unused int argc, const __unused char **argv)
669{
670	/*
671	 * We create a child process to hold the lock which we will
672	 * test. We use a pipe to communicate with the child.
673	 */
674	int pid;
675	int pfd[2];
676	struct flock fl;
677	char ch;
678	int res;
679
680	if (pipe(pfd) < 0)
681		err(1, "pipe");
682
683	fl.l_start = 0;
684	fl.l_len = 0;
685	fl.l_type = F_RDLCK;
686	fl.l_whence = SEEK_SET;
687
688	pid = fork();
689	if (pid < 0)
690		err(1, "fork");
691
692	if (pid == 0) {
693		/*
694		 * We are the child. We set a write lock and then
695		 * write one byte back to the parent to tell it. The
696		 * parent will kill us when its done.
697		 */
698		if (fcntl(fd, F_SETLK, &fl) < 0)
699			err(1, "F_SETLK (child)");
700		if (write(pfd[1], "a", 1) < 0)
701			err(1, "writing to pipe (child)");
702		pause();
703		exit(0);
704	}
705
706	/*
707	 * Wait until the child has set its lock and then perform the
708	 * test.
709	 */
710	if (read(pfd[0], &ch, 1) != 1)
711		err(1, "reading from pipe (child)");
712
713	/*
714	 * fcntl should wait until the alarm and then return -1 with
715	 * errno set to EINTR.
716	 */
717	printf("8 - F_SETLK shared lock on share locked region: ");
718
719	fl.l_type = F_RDLCK;
720	res = fcntl(fd, F_SETLK, &fl);
721
722	kill(pid, SIGTERM);
723	safe_waitpid(pid);
724	close(pfd[0]);
725	close(pfd[1]);
726
727	fl.l_start = 0;
728	fl.l_len = 0;
729	fl.l_type = F_UNLCK;
730	if (fcntl(fd, F_SETLK, &fl) < 0)
731		err(1, "F_UNLCK");
732
733	FAIL(res != 0);
734
735	SUCCEED;
736}
737
738/*
739 * Test 9 - F_SETLK exclusive lock on share locked region
740 *
741 * If a shared or exclusive lock cannot be set, fcntl returns
742 * immediately with EACCES or EAGAIN.
743 */
744static int
745test9(int fd, __unused int argc, const __unused char **argv)
746{
747	/*
748	 * We create a child process to hold the lock which we will
749	 * test. We use a pipe to communicate with the child.
750	 */
751	int pid;
752	int pfd[2];
753	struct flock fl;
754	char ch;
755	int res;
756
757	if (pipe(pfd) < 0)
758		err(1, "pipe");
759
760	fl.l_start = 0;
761	fl.l_len = 0;
762	fl.l_type = F_RDLCK;
763	fl.l_whence = SEEK_SET;
764
765	pid = fork();
766	if (pid < 0)
767		err(1, "fork");
768
769	if (pid == 0) {
770		/*
771		 * We are the child. We set a write lock and then
772		 * write one byte back to the parent to tell it. The
773		 * parent will kill us when its done.
774		 */
775		if (fcntl(fd, F_SETLK, &fl) < 0)
776			err(1, "F_SETLK (child)");
777		if (write(pfd[1], "a", 1) < 0)
778			err(1, "writing to pipe (child)");
779		pause();
780		exit(0);
781	}
782
783	/*
784	 * Wait until the child has set its lock and then perform the
785	 * test.
786	 */
787	if (read(pfd[0], &ch, 1) != 1)
788		err(1, "reading from pipe (child)");
789
790	/*
791	 * fcntl should wait until the alarm and then return -1 with
792	 * errno set to EINTR.
793	 */
794	printf("9 - F_SETLK exclusive lock on share locked region: ");
795
796	fl.l_type = F_WRLCK;
797	res = fcntl(fd, F_SETLK, &fl);
798	kill(pid, SIGTERM);
799	safe_waitpid(pid);
800	close(pfd[0]);
801	close(pfd[1]);
802
803	FAIL(res == 0);
804	FAIL(errno != EACCES && errno != EAGAIN);
805
806	SUCCEED;
807}
808
809/*
810 * Test 10 - trying to set bogus pid or sysid values
811 *
812 * The l_pid and l_sysid fields are only used with F_GETLK to return
813 * the process ID of the process holding a blocking lock and the
814 * system ID of the system that owns that process
815 */
816static int
817test10(int fd, __unused int argc, const __unused char **argv)
818{
819	/*
820	 * We create a child process to hold the lock which we will
821	 * test. We use a pipe to communicate with the child.
822	 */
823	int pid;
824	int pfd[2];
825	struct flock fl;
826	char ch;
827
828	if (pipe(pfd) < 0)
829		err(1, "pipe");
830
831	fl.l_start = 0;
832	fl.l_len = 0;
833	fl.l_type = F_WRLCK;
834	fl.l_whence = SEEK_SET;
835	fl.l_pid = 9999;
836#ifdef HAVE_SYSID
837	fl.l_sysid = 9999;
838#endif
839
840	pid = fork();
841	if (pid < 0)
842		err(1, "fork");
843
844	if (pid == 0) {
845		/*
846		 * We are the child. We set a write lock and then
847		 * write one byte back to the parent to tell it. The
848		 * parent will kill us when its done.
849		 */
850		if (fcntl(fd, F_SETLK, &fl) < 0)
851			err(1, "F_SETLK (child)");
852		if (write(pfd[1], "a", 1) < 0)
853			err(1, "writing to pipe (child)");
854		pause();
855		exit(0);
856	}
857
858	/*
859	 * Wait until the child has set its lock and then perform the
860	 * test.
861	 */
862	if (read(pfd[0], &ch, 1) != 1)
863		err(1, "reading from pipe (child)");
864
865	printf("10 - trying to set bogus pid or sysid values: ");
866
867	if (fcntl(fd, F_GETLK, &fl) < 0)
868		err(1, "F_GETLK");
869
870	kill(pid, SIGTERM);
871	safe_waitpid(pid);
872	close(pfd[0]);
873	close(pfd[1]);
874
875	FAIL(fl.l_pid != pid);
876#ifdef HAVE_SYSID
877	FAIL(fl.l_sysid != 0);
878#endif
879
880	SUCCEED;
881}
882
883/*
884 * Test 11 - remote locks
885 *
886 * XXX temporary interface which will be removed when the kernel lockd
887 * is added.
888 */
889static int
890test11(int fd, __unused int argc, const __unused char **argv)
891{
892#ifdef F_SETLK_REMOTE
893	struct flock fl;
894	int res;
895
896	if (geteuid() != 0)
897		return 0;
898
899	fl.l_start = 0;
900	fl.l_len = 0;
901	fl.l_type = F_WRLCK;
902	fl.l_whence = SEEK_SET;
903	fl.l_pid = 9999;
904	fl.l_sysid = 1001;
905
906	printf("11 - remote locks: ");
907
908	res = fcntl(fd, F_SETLK_REMOTE, &fl);
909	FAIL(res != 0);
910
911	fl.l_sysid = 1002;
912	res = fcntl(fd, F_SETLK_REMOTE, &fl);
913	FAIL(res == 0);
914	FAIL(errno != EACCES && errno != EAGAIN);
915
916	res = fcntl(fd, F_GETLK, &fl);
917	FAIL(res != 0);
918	FAIL(fl.l_pid != 9999);
919	FAIL(fl.l_sysid != 1001);
920
921	fl.l_type = F_UNLCK;
922	fl.l_sysid = 1001;
923	fl.l_start = 0;
924	fl.l_len = 0;
925	res = fcntl(fd, F_SETLK_REMOTE, &fl);
926	FAIL(res != 0);
927
928	fl.l_pid = 1234;
929	fl.l_sysid = 1001;
930	fl.l_start = 0;
931	fl.l_len = 1;
932	fl.l_whence = SEEK_SET;
933	fl.l_type = F_RDLCK;
934	res = fcntl(fd, F_SETLK_REMOTE, &fl);
935	FAIL(res != 0);
936
937	fl.l_sysid = 1002;
938	res = fcntl(fd, F_SETLK_REMOTE, &fl);
939	FAIL(res != 0);
940
941	fl.l_type = F_UNLCKSYS;
942	fl.l_sysid = 1001;
943	res = fcntl(fd, F_SETLK_REMOTE, &fl);
944	FAIL(res != 0);
945
946	fl.l_type = F_WRLCK;
947	res = fcntl(fd, F_GETLK, &fl);
948	FAIL(res != 0);
949	FAIL(fl.l_pid != 1234);
950	FAIL(fl.l_sysid != 1002);
951
952	fl.l_type = F_UNLCKSYS;
953	fl.l_sysid = 1002;
954	res = fcntl(fd, F_SETLK_REMOTE, &fl);
955	FAIL(res != 0);
956
957	SUCCEED;
958#else
959	return 0;
960#endif
961}
962
963/*
964 * Test 12 - F_SETLKW on locked region which is then unlocked
965 *
966 * If a shared or exclusive lock is blocked by other locks, the
967 * process waits until the request can be satisfied.
968 */
969static int
970test12(int fd, __unused int argc, const __unused char **argv)
971{
972	/*
973	 * We create a child process to hold the lock which we will
974	 * test. We use a pipe to communicate with the child.
975	 */
976	int pid;
977	int pfd[2];
978	struct flock fl;
979	char ch;
980	int res;
981
982	if (pipe(pfd) < 0)
983		err(1, "pipe");
984
985	fl.l_start = 0;
986	fl.l_len = 0;
987	fl.l_type = F_WRLCK;
988	fl.l_whence = SEEK_SET;
989
990	pid = fork();
991	if (pid < 0)
992		err(1, "fork");
993
994	if (pid == 0) {
995		/*
996		 * We are the child. We set a write lock and then
997		 * write one byte back to the parent to tell it. The
998		 * parent will kill us when its done.
999		 */
1000		if (fcntl(fd, F_SETLK, &fl) < 0)
1001			err(1, "F_SETLK (child)");
1002		if (write(pfd[1], "a", 1) < 0)
1003			err(1, "writing to pipe (child)");
1004
1005		sleep(1);
1006		exit(0);
1007	}
1008
1009	/*
1010	 * Wait until the child has set its lock and then perform the
1011	 * test.
1012	 */
1013	if (read(pfd[0], &ch, 1) != 1)
1014		err(1, "reading from pipe (child)");
1015
1016	/*
1017	 * fcntl should wait until the alarm and then return -1 with
1018	 * errno set to EINTR.
1019	 */
1020	printf("12 - F_SETLKW on locked region which is then unlocked: ");
1021
1022	//alarm(1);
1023
1024	res = fcntl(fd, F_SETLKW, &fl);
1025	kill(pid, SIGTERM);
1026	safe_waitpid(pid);
1027	close(pfd[0]);
1028	close(pfd[1]);
1029	FAIL(res != 0);
1030
1031	fl.l_start = 0;
1032	fl.l_len = 0;
1033	fl.l_type = F_UNLCK;
1034	if (fcntl(fd, F_SETLK, &fl) < 0)
1035		err(1, "F_UNLCK");
1036
1037	SUCCEED;
1038}
1039
1040/*
1041 * Test 13 - F_SETLKW on locked region, race with owner
1042 *
1043 * If a shared or exclusive lock is blocked by other locks, the
1044 * process waits until the request can be satisfied.
1045 */
1046static int
1047test13(int fd, __unused int argc, const __unused char **argv)
1048{
1049	/*
1050	 * We create a child process to hold the lock which we will
1051	 * test. We use a pipe to communicate with the child.
1052	 */
1053	int i;
1054	int pid;
1055	int pfd[2];
1056	struct flock fl;
1057	char ch;
1058	int res;
1059	struct itimerval itv;
1060
1061	printf("13 - F_SETLKW on locked region, race with owner: ");
1062	fflush(stdout);
1063
1064	for (i = 0; i < 100; i++) {
1065		if (pipe(pfd) < 0)
1066			err(1, "pipe");
1067
1068		fl.l_start = 0;
1069		fl.l_len = 0;
1070		fl.l_type = F_WRLCK;
1071		fl.l_whence = SEEK_SET;
1072
1073		pid = fork();
1074		if (pid < 0)
1075			err(1, "fork");
1076
1077		if (pid == 0) {
1078			/*
1079			 * We are the child. We set a write lock and then
1080			 * write one byte back to the parent to tell it. The
1081			 * parent will kill us when its done.
1082			 */
1083			if (fcntl(fd, F_SETLK, &fl) < 0)
1084				err(1, "F_SETLK (child)");
1085			if (write(pfd[1], "a", 1) < 0)
1086				err(1, "writing to pipe (child)");
1087
1088			usleep(1);
1089			exit(0);
1090		}
1091
1092		/*
1093		 * Wait until the child has set its lock and then perform the
1094		 * test.
1095		 */
1096		while (read(pfd[0], &ch, 1) != 1) {
1097			if (errno == EINTR)
1098				continue;
1099			err(1, "reading from pipe (child)");
1100		}
1101
1102		/*
1103		 * fcntl should wait until the alarm and then return -1 with
1104		 * errno set to EINTR.
1105		 */
1106		itv.it_interval.tv_sec = 0;
1107		itv.it_interval.tv_usec = 0;
1108		itv.it_value.tv_sec = 0;
1109		itv.it_value.tv_usec = 2;
1110		setitimer(ITIMER_REAL, &itv, NULL);
1111
1112		res = fcntl(fd, F_SETLKW, &fl);
1113		kill(pid, SIGTERM);
1114		safe_waitpid(pid);
1115		close(pfd[0]);
1116		close(pfd[1]);
1117		FAIL(!(res == 0 || (res == -1 && errno == EINTR)));
1118
1119		fl.l_start = 0;
1120		fl.l_len = 0;
1121		fl.l_type = F_UNLCK;
1122		if (fcntl(fd, F_SETLK, &fl) < 0)
1123			err(1, "F_UNLCK");
1124	}
1125	SUCCEED;
1126}
1127
1128/*
1129 * Test 14 - soak test
1130 */
1131static int
1132test14(int fd, int argc, const char **argv)
1133{
1134#define CHILD_COUNT 20
1135	/*
1136	 * We create a set of child processes and let each one run
1137	 * through a random sequence of locks and unlocks.
1138	 */
1139	int i, j, id, id_base;
1140	int pids[CHILD_COUNT], pid;
1141	char buf[128];
1142	char tbuf[128];
1143	int map[128];
1144	char outbuf[512];
1145	struct flock fl;
1146	struct itimerval itv;
1147	int status;
1148
1149	id_base = 0;
1150	if (argc >= 2)
1151		id_base = strtol(argv[1], NULL, 0);
1152
1153	printf("14 - soak test: ");
1154	fflush(stdout);
1155
1156	for (i = 0; i < 128; i++)
1157		map[i] = F_UNLCK;
1158
1159	for (i = 0; i < CHILD_COUNT; i++) {
1160
1161		pid = fork();
1162		if (pid < 0)
1163			err(1, "fork");
1164		if (pid) {
1165			/*
1166			 * Parent - record the pid and continue.
1167			 */
1168			pids[i] = pid;
1169			continue;
1170		}
1171
1172		/*
1173		 * Child - do some work and exit.
1174		 */
1175		id = id_base + i;
1176		srandom(getpid());
1177
1178		for (j = 0; j < 50; j++) {
1179			int start, end, len;
1180			int set, wrlock;
1181
1182			do {
1183				start = random() & 127;
1184				end = random() & 127;
1185			} while (end <= start);
1186
1187			set = random() & 1;
1188			wrlock = random() & 1;
1189
1190			len = end - start;
1191			fl.l_start = start;
1192			fl.l_len = len;
1193			fl.l_whence = SEEK_SET;
1194			if (set)
1195				fl.l_type = wrlock ? F_WRLCK : F_RDLCK;
1196			else
1197				fl.l_type = F_UNLCK;
1198
1199			itv.it_interval.tv_sec = 0;
1200			itv.it_interval.tv_usec = 0;
1201			itv.it_value.tv_sec = 0;
1202			itv.it_value.tv_usec = 3000;
1203			setitimer(ITIMER_REAL, &itv, NULL);
1204
1205			if (fcntl(fd, F_SETLKW, &fl) < 0) {
1206				if (errno == EDEADLK || errno == EINTR) {
1207					if (verbose) {
1208						snprintf(outbuf, sizeof(outbuf),
1209						    "%d[%d]: %s [%d .. %d] %s\n",
1210						    id, j,
1211						    set ? (wrlock ? "write lock"
1212							: "read lock")
1213						    : "unlock", start, end,
1214						    errno == EDEADLK
1215						    ? "deadlock"
1216						    : "interrupted");
1217						write(1, outbuf,
1218						    strlen(outbuf));
1219					}
1220					continue;
1221				} else {
1222					perror("fcntl");
1223				}
1224			}
1225
1226			itv.it_interval.tv_sec = 0;
1227			itv.it_interval.tv_usec = 0;
1228			itv.it_value.tv_sec = 0;
1229			itv.it_value.tv_usec = 0;
1230			setitimer(ITIMER_REAL, &itv, NULL);
1231
1232			if (verbose) {
1233				snprintf(outbuf, sizeof(outbuf),
1234				    "%d[%d]: %s [%d .. %d] succeeded\n",
1235				    id, j,
1236				    set ? (wrlock ? "write lock" : "read lock")
1237				    : "unlock", start, end);
1238				write(1, outbuf, strlen(outbuf));
1239			}
1240
1241			if (set) {
1242				if (wrlock) {
1243					/*
1244					 * We got a write lock - write
1245					 * our ID to each byte that we
1246					 * managed to claim.
1247					 */
1248					for (i = start; i < end; i++)
1249						map[i] = F_WRLCK;
1250					memset(&buf[start], id, len);
1251					if (pwrite(fd, &buf[start], len,
1252						start) != len) {
1253						printf("%d: short write\n", id);
1254						exit(1);
1255					}
1256				} else {
1257					/*
1258					 * We got a read lock - read
1259					 * the bytes which we claimed
1260					 * so that we can check that
1261					 * they don't change
1262					 * unexpectedly.
1263					 */
1264					for (i = start; i < end; i++)
1265						map[i] = F_RDLCK;
1266					if (pread(fd, &buf[start], len,
1267						start) != len) {
1268						printf("%d: short read\n", id);
1269						exit(1);
1270					}
1271				}
1272			} else {
1273				for (i = start; i < end; i++)
1274					map[i] = F_UNLCK;
1275			}
1276
1277			usleep(1000);
1278
1279			/*
1280			 * Read back the whole region so that we can
1281			 * check that all the bytes we have some kind
1282			 * of claim to have the correct value.
1283			 */
1284			if (pread(fd, tbuf, sizeof(tbuf), 0) != sizeof(tbuf)) {
1285				printf("%d: short read\n", id);
1286				exit(1);
1287			}
1288
1289			for (i = 0; i < 128; i++) {
1290				if (map[i] != F_UNLCK && buf[i] != tbuf[i]) {
1291					snprintf(outbuf, sizeof(outbuf),
1292					    "%d: byte %d expected %d, "
1293					    "got %d\n", id, i, buf[i], tbuf[i]);
1294					write(1, outbuf, strlen(outbuf));
1295					exit(1);
1296				}
1297			}
1298		}
1299		if (verbose)
1300			printf("%d[%d]: done\n", id, j);
1301
1302		exit(0);
1303	}
1304
1305	status = 0;
1306	for (i = 0; i < CHILD_COUNT; i++) {
1307		status += safe_waitpid(pids[i]);
1308	}
1309	if (status)
1310		FAIL(status != 0);
1311
1312	SUCCEED;
1313}
1314
1315/*
1316 * Test 15 - flock(2) semantcs
1317 *
1318 * When a lock holder has a shared lock and attempts to upgrade that
1319 * shared lock to exclusive, it must drop the shared lock before
1320 * blocking on the exclusive lock.
1321 *
1322 * To test this, we first arrange for two shared locks on the file,
1323 * and then attempt to upgrade one of them to exclusive. This should
1324 * drop one of the shared locks and block. We interrupt the blocking
1325 * lock request and examine the lock state of the file after dropping
1326 * the other shared lock - there should be no active locks at this
1327 * point.
1328 */
1329static int
1330test15(int fd, __unused int argc, const __unused char **argv)
1331{
1332#ifdef LOCK_EX
1333	/*
1334	 * We create a child process to hold the lock which we will
1335	 * test. We use a pipe to communicate with the child.
1336	 *
1337	 * Since we only have one file descriptors and lock ownership
1338	 * for flock(2) goes with the file descriptor, we use fcntl to
1339	 * set the child's shared lock.
1340	 */
1341	int pid;
1342	int pfd[2];
1343	struct flock fl;
1344	char ch;
1345	int res;
1346
1347	if (pipe(pfd) < 0)
1348		err(1, "pipe");
1349
1350	pid = fork();
1351	if (pid < 0)
1352		err(1, "fork");
1353
1354	if (pid == 0) {
1355		/*
1356		 * We are the child. We set a shared lock and then
1357		 * write one byte back to the parent to tell it. The
1358		 * parent will kill us when its done.
1359		 */
1360		fl.l_start = 0;
1361		fl.l_len = 0;
1362		fl.l_type = F_RDLCK;
1363		fl.l_whence = SEEK_SET;
1364		if (fcntl(fd, F_SETLK, &fl) < 0)
1365			err(1, "fcntl(F_SETLK) (child)");
1366		if (write(pfd[1], "a", 1) < 0)
1367			err(1, "writing to pipe (child)");
1368		pause();
1369		exit(0);
1370	}
1371
1372	/*
1373	 * Wait until the child has set its lock and then perform the
1374	 * test.
1375	 */
1376	if (read(pfd[0], &ch, 1) != 1)
1377		err(1, "reading from pipe (child)");
1378
1379	(void)dup(fd);
1380	if (flock(fd, LOCK_SH) < 0)
1381		err(1, "flock shared");
1382
1383	/*
1384	 * flock should wait until the alarm and then return -1 with
1385	 * errno set to EINTR.
1386	 */
1387	printf("15 - flock(2) semantics: ");
1388
1389	alarm(1);
1390	flock(fd, LOCK_EX);
1391
1392	/*
1393	 * Kill the child to force it to drop its locks.
1394	 */
1395	kill(pid, SIGTERM);
1396	safe_waitpid(pid);
1397
1398	fl.l_start = 0;
1399	fl.l_len = 0;
1400	fl.l_type = F_WRLCK;
1401	fl.l_whence = SEEK_SET;
1402	res = fcntl(fd, F_GETLK, &fl);
1403
1404	close(pfd[0]);
1405	close(pfd[1]);
1406	FAIL(res != 0);
1407	FAIL(fl.l_type != F_UNLCK);
1408
1409	SUCCEED;
1410#else
1411	return 0;
1412#endif
1413}
1414
1415struct test_ctx {
1416	struct flock tc_fl;
1417	int tc_fd;
1418};
1419
1420static void *
1421test16_func(void *tc_in)
1422{
1423	uintptr_t error;
1424	struct test_ctx *tc = tc_in;
1425
1426	error = fcntl(tc->tc_fd, F_SETLKW, &tc->tc_fl);
1427
1428	pthread_exit((void *)error);
1429}
1430
1431#define THREADS 10
1432
1433/*
1434 * Test 16 - F_SETLKW from two threads
1435 *
1436 * If two threads within a process are blocked on a lock and the lock
1437 * is granted, make sure things are sane.
1438 */
1439static int
1440test16(int fd, __unused int argc, const __unused char **argv)
1441{
1442	/*
1443	 * We create a child process to hold the lock which we will
1444	 * test. We use a pipe to communicate with the child.
1445	 */
1446	int pid;
1447	int pfd[2];
1448	struct test_ctx tc = { .tc_fd = fd };
1449	char ch;
1450	int i;
1451	int error;
1452	pthread_t thr[THREADS];
1453
1454	if (pipe(pfd) < 0)
1455		err(1, "pipe");
1456
1457	tc.tc_fl.l_start = 0;
1458	tc.tc_fl.l_len = 0;
1459	tc.tc_fl.l_type = F_WRLCK;
1460	tc.tc_fl.l_whence = SEEK_SET;
1461
1462	pid = fork();
1463	if (pid < 0)
1464		err(1, "fork");
1465
1466	if (pid == 0) {
1467		/*
1468		 * We are the child. We set a write lock and then
1469		 * write one byte back to the parent to tell it. The
1470		 * parent will kill us when its done.
1471		 */
1472		if (fcntl(fd, F_SETLK, &tc.tc_fl) < 0)
1473			err(1, "F_SETLK (child)");
1474		if (write(pfd[1], "a", 1) < 0)
1475			err(1, "writing to pipe (child)");
1476		pause();
1477		exit(0);
1478	}
1479
1480	/*
1481	 * Wait until the child has set its lock and then perform the
1482	 * test.
1483	 */
1484	if (read(pfd[0], &ch, 1) != 1)
1485		err(1, "reading from pipe (child)");
1486
1487	/*
1488	 * fcntl should wait until the alarm and then return -1 with
1489	 * errno set to EINTR.
1490	 */
1491	printf("16 - F_SETLKW on locked region by two threads: ");
1492
1493	for (i = 0; i < THREADS; i++) {
1494		error = pthread_create(&thr[i], NULL, test16_func, &tc);
1495		if (error)
1496			err(1, "pthread_create");
1497	}
1498
1499	/*
1500	 * Sleep, then kill the child. This makes me a little sad, but it's
1501	 * tricky to tell whether the threads are all really blocked by this
1502	 * point.
1503	 */
1504	sleep(1);
1505	kill(pid, SIGTERM);
1506	safe_waitpid(pid);
1507	close(pfd[0]);
1508	close(pfd[1]);
1509
1510	for (i = 0; i < THREADS; i++) {
1511		void *res;
1512		error = pthread_join(thr[i], &res);
1513		if (error)
1514			err(1, "pthread_join");
1515		FAIL((uintptr_t)res != 0);
1516	}
1517
1518	SUCCEED;
1519}
1520
1521struct test {
1522	int (*testfn)(int, int, const char **);	/* function to perform the test */
1523	int num;		/* test number */
1524	int intr;		/* non-zero if the test interrupts a lock */
1525};
1526
1527static struct test tests[] = {
1528	{	test1,		1,	0	},
1529	{	test2,		2,	0	},
1530	{	test3,		3,	1	},
1531	{	test4,		4,	0	},
1532	{	test5,		5,	1	},
1533	{	test6,		6,	1	},
1534	{	test7,		7,	0	},
1535	{	test8,		8,	0	},
1536	{	test9,		9,	0	},
1537	{	test10,		10,	0	},
1538	{	test11,		11,	1	},
1539	{	test12,		12,	0	},
1540	{	test13,		13,	1	},
1541	{	test14,		14,	0	},
1542	{	test15,		15,	1	},
1543	{	test16,		16,	1	},
1544};
1545
1546int
1547main(int argc, const char *argv[])
1548{
1549	int testnum;
1550	int fd;
1551	int nointr;
1552	unsigned i;
1553	struct sigaction sa;
1554	int test_argc;
1555	const char **test_argv;
1556
1557	if (argc < 2) {
1558		errx(1, "usage: flock <directory> [test number] ...");
1559	}
1560
1561	fd = make_file(argv[1], 1024);
1562	if (argc >= 3) {
1563		testnum = strtol(argv[2], NULL, 0);
1564		test_argc = argc - 2;
1565		test_argv = argv + 2;
1566	} else {
1567		testnum = 0;
1568		test_argc = 0;
1569		test_argv = NULL;
1570	}
1571
1572	sa.sa_handler = ignore_alarm;
1573	sigemptyset(&sa.sa_mask);
1574	sa.sa_flags = 0;
1575	sigaction(SIGALRM, &sa, 0);
1576
1577	nointr = 0;
1578#if defined(__FreeBSD__) && __FreeBSD_version < 800040
1579	{
1580		/*
1581		 * FreeBSD with userland NLM can't interrupt a blocked
1582		 * lock request on an NFS mounted filesystem.
1583		 */
1584		struct statfs st;
1585		fstatfs(fd, &st);
1586		nointr = !strcmp(st.f_fstypename, "nfs");
1587	}
1588#endif
1589
1590	for (i = 0; i < nitems(tests); i++) {
1591		if (tests[i].intr && nointr)
1592			continue;
1593		if (!testnum || tests[i].num == testnum)
1594			tests[i].testfn(fd, test_argc, test_argv);
1595	}
1596
1597	return 0;
1598}
1599